serhii.net

In the middle of the desert you can say anything you want

22 Jan 2024

UA-CBT story generation Masterarbeit notes

Instead of doing graphs for 231024-1704 Master thesis task CBT, went with generating prompts for stories.

General

If you want a story involving a fox and a raven, the story will contain cheese — so need to inject randomness.

Models

Prompt used:

Write an interesting story in the style of Terry Pratchett, with at least 2 recurring major characters and 3 minor, of different genders. Don’t start the story by listing the characters. None of the characters should have names. All should be animals. The story should be graduate student reading level. Please make it rather detailed than generic - don’t mention that X had to Y, but show/tell him doing that. It should be about an apprentice’s revenge over his master. The main plot point should revolve around corruption. The story should have a bad ending. Write the story in the Ukrainian language. Start with the words: Одного разу,

Gpt

4

..is really good if you tell it what it wants. In Ukr as well.

The info that story should be in Ukrainian should be at the end, or “start the story with”.

3
  • Adds Russian phrasings etc. at the end, and is kinda literal in its understanding.
  • sometimes grammatically wrong

Одного разу, у містечку Анімалопіліс, де жили різні тварини, трапилася ця історія. В місті панувала глибока корупція, але це не виглядало так просто, як здається. У містечку жили два головні персонажі: Майстер Сова і Лицар Заєць. Також були три менш важливі персонажі: Лисичка, Ведмідь та Жаба. … Але план зійшов на нет, коли виявилось, що Майстер Сова дізнався про зраду. Він впіймав Лицаря Зайця, коли він намагався передати докази Лисичці, Ведмедю та Жабі. Майстер Сова вирішив застосувати свою владу та покарати Лицаря Зайця.

Зараз Лицар Заєць перебуває у в’язниці, а корупція в Анімалопілісі продовжує рости. Лисичка, Ведмідь та Жаба вже не намагаються боротися з нею, а мешканці міста стали байдужими до цього проблеми. Так завершується ця історія, де корупція перемогла, а справедливість поступилася владі та грошам.

meister Fuchs 2024-01-22-102341_989x876_scrot 1.png

Codellama-34b-instruct:

  • 2024-01-22-103123_897x156_scrot.png

  • primitive but in Ukrainian

  • here’s a list of friends of the fox Lisa (=Russian word for fox written in Ukrainian letters) that will help her with her revenge about the wolf Wolf:

    • a rabbit named Rabbit
    • an otter named Otter
    • a frog named Frog
  • mixtral-7b-instruct

    • My God
    • 2024-01-22-103327_926x226_scrot.png
      • not the highlighted word, basically all of it
  • Fazit

    • gpt4 is the best, others are bad
      • uninteresting and primitive in the best case
      • most ignore “should not have names”
      • most add non-Ukr language

It would be interesting to parametrize/analyze:

  • by which LM I used to generate it
  • by reading level
  • comparing with real stories and stories made to look like real ones

Humanities

Looking for Ukrainian tales as controls found this:

When folklore began to be intensively collected, eastern Ukraine was part of the Russian Empire and western Ukraine was part of Austro-Hungary. In eastern Ukraine, activities that might encourage Ukrainian nationalist feelings were banned, but folklore was not. Russians saw Ukraine as a backward, border place: Little Russia, as Ukraine was so often called. They also saw folklore as ignorant, country literature, appropriate to their perception of Ukraine. Russians felt that the collection of Ukrainian folklore, by perpetuating the image of Ukrainian backwardness, would foster the subjugation of Ukraine. Therefore, they permitted the extensive scholarly activity from which we draw so much of our information today. Ironically, when Ukrainian folklore was published, it was often published not as Ukrainian material, but as a subdivision of Russian folklore. Thus Aleksandr Afanas’ev’s famous collection, Russian Folk Tales, is not strictly a collection of Russian tales at all, but one that includes Ukrainian and Belarusian tales alongside the Russian ones. Because Ukraine was labeled Little Russia and its language was considered a distant dialect of Russian, its folklore was seen as subsumable under Russian folklore. Russia supposedly consisted of three parts: Great Russia, what we call Russia today; Little Russia, or Ukraine; and White Russia, what we now call Belarus. The latter two could beand often wereincluded under Great Russia. Some of the material drawn on here comes from books that nominally contain Russian folktales or Russian legends. We know that they are actually Ukrainian because we can easily distinguish the Ukrainian language from Russian. Sometimes Ukrainian tales appear in Russian translation to make them more accessible to a Russian reading public. In these instances we can discern their Ukrainian origin if the place where a tale or legend was collected is given in the index or the notes. 1

This feels relevant as well: The Politics of innocence: Soviet and Post-Soviet Animation on Folklore topics | Journal of American Folklore | Scholarly Publishing Collective

OpenAI

Tokens Used: 3349
        Prompt Tokens: 300
        Completion Tokens: 3049
Successful Requests: 2
Total Cost (USD): $0.09447

So it’s about 0.05 per generated story? Somehow way more than I expected.

~300 stories (3 instances from each) would be around 15€

I mean I can happily generate around 100 manually per day from the ChatGPT interface. And I can immediately proofread it as I go and while a different story is being generated. (I can also manually fix gpt3 stories generated for 1/10th of the price.)

I guess not that much more of a workload. And most importantly - it would give me a better insight about possible issues with the stories, so I can change the prompts quickly, instead of generating 300 ‘bad’ ones.

I need to think of a workflow to (grammatically) correct these stories. I assume writing each story to a file named after the row, manually correcting it, and then automatically adding to the new column?

(Either way, having generated 10 stories for 40 cents, I’ll analyze them at home and think about it all.)

It boils down to how many training instances can I get from a story — tomorrow I’ll experiment with it and we’ll see.

Stories review

The stories contain errors but ChatGPT can fix them! But manual checking is heavily needed, and, well, this will also be part of the Masterarbeit.

The fixes sometimes are really good and sometimes not: 2024-01-23-135432_863x655_scrot.png

I tried to experiment with telling it to avoid errors and Russian, with inconclusive results. I won’t add this to the prompt.

Колись давним-давно, у лісі, де дерева шепотіли таємницями, а квіти вигравали у вічному танці з вітром, жила духмяна метелик.

(and then goes on to use the feminine gender for it throughout the entire tale)

On second thought, this could be better:

 All should be animals. None of the characters should have names, but should be referred to by pronouns and the capitalized name of their species.  

I can use the capitalized nouns as keys, and then “до мудрого Сови” doesn’t feel awkward?..

This might be even better:

None of the characters should have names: they should be referred to by the capitalized name of their species (and pronouns), and their gender should be the same as that name of their species.

The story should be about an owl helping their mentor, a frog, with an embarassing problem. The story should be in the Ukrainian language.

2024-01-23-185532_549x121_scrot.png

And also remove the bit about different genders, or same gender, just let it be.

Yes, let this be the prompt v2 v3. Fixed the genders in the options, removed the genders limit in the prompt.

None of the characters should have names: they should be referred to by the name of their species, and their gender should be the same as that name of their species. {ALL_SHOULD_BE_ANIMAL

Takes about 4 cents and 140 seconds per story:

  1%|▌                                            | 4/300 [11:39<14:23:02, 174.94s/it]
INFO:__main__:Total price for the session: 0.22959999999999997 (5 stories).

2024-01-24-125204_691x637_scrot.png

“Кішка обіцяла довести, що вона гідний син” that’s on me.

Removed gendered “son”.

Через деякий час до верблюда прийшла газель, яка просила допомоги. Її стадо зазнало нападу від лева, і вона шукала поради, як уникнути подібних інцидентів у майбутньому. Верблюд порадив газелі знайти нові пасовища, де леви не полюють, і навчити стадо бути більш обережними та уважними.

  • метелик відчула непереборне бажання знайти найсолодший квітка в лісі

    • Метелик/бабочка, квітка/цветок. Both errors Russian-influenced.

Tokenization and length

Ця історія відбулась у місті, де вулиці були вимощені старою бруківкою, а будинки були ніби з казок. Миша, зі своїм сірим хутром таблискучими очима, була відома серед мешканців міста своєю ненаситною жадібністю. Вона не просто збирала зернятка та крихти, що їй вдавалося знайти, але й намагалася відібрати їжу у інших. This has 264 tokens for bert-base-uncased, 106 for bert-base-multilingual-uncased.

import transformers
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
tokenizer.tokenize("s")

A ’typical’ longer story is 901 multilinugal tokens. Damn. (Or 709 for KoichiYasuoka/roberta-base-ukrainian · Hugging Face)

Practically this means shorter stories? Cutting bits at the end? Separating them? Using tokens instead of sentences when creating tasks?

… The story should have an unhappy ending. It should be no more than 300 words long.

The story should be about a cunning camel not learning anything.

Колись давним-давно, в піщаних просторах пустелі, жив хитрий верблюд. Він був відомий своєю вмінням уникати праці, перекладаючи свої обов'язки на менш кмітливих сусідів - невеликого єнота та серйозного орла. Вони терпеливо виконували важку роботу, в той час як верблюд ласував найсолодшими пагонами.

Одного дня, коли вода в оазі на межі висихання, верблюд вирішив, що єнот і орел повинні відправитись у небезпечну подорож за новим джерелом. "Тільки ви маєте кмітливість і силу знайти воду," - лукаво мовив верблюд.

Єнот і орел, виснажені його маніпуляціями, нарешті усвідомили хитрість верблюда і вирішили діяти спільно. Вони пішли, обіцяючи верблюду привести воду, але насправді вони планували знайти нову оазу лише для себе.

Залишившись на самоті, верблюд швидко зрозумів, що його власна лінь і хитрість привели до катастрофи. Орел і єнот знайшли нове місце, а верблюд, не здатний самостійно вижити, був змушений мандрувати пустелею у пошуках води і допомоги.

Але пустеля була невблаганною, і верблюд, нарешті, зрозумів, що хитрість без мудрості і співпраці - це шлях до самотності та відчаю. Саме ця думка була його останньою, перш ніж пустеля поглинула його.

175 words, 298 tokens for roberta-base-ukrainian, 416 for bert-base-multilingual-uncased. 10 sentences. I think I’ll add this to the template v4.

Back to CBT task creation

Problem: animacy detection is shaky at best:

(Pdb++) for a in matches: print(a, a[0].morph.get("Animacy"))
верблюду ['Inan']
воду ['Inan']
оазу ['Inan']
самоті ['Inan']
верблюд ['Anim']
(Pdb++) for w in doc:  print(w, w.morph.get("Animacy")[0]) if w.morph.get("Animacy")==["Anim"] else None
верблюд Anim
кмітливих Anim
сусідів Anim
невеликого Anim
єнота Anim
серйозного Anim
орла Anim
верблюд Anim
верблюд Anim
орел Anim
ви Anim
верблюд Anim
Єнот Anim
орел Anim
верблюда Anim
верблюд Anim
Орел Anim
верблюд Anim
верблюд Anim

OK, so anim has a higher precision than recall. And adj can also be animate, which is logical!

I think I can handle the errors.

More issues:

  • Миша can be parsed as a PROPN w/ t.morph Animacy=Anim|Case=Nom|Gender=Fem|NameType=Giv|Number=Sing
(Pdb++) tt = [t for t in doc if t.pos_ == PROPN]
(Pdb++) tt
[Миша, Собака, Миша, Кіт, Мишею, Ластівка, Ластівка, Мишу, Миша, Ластівка, Миша, Кіт, Миша, Миша, Миша, Миші, Мишу, Ластівка, Миші, Миші, Миша]

damn. OK, so propn happens because capitalization only? Wow.

  • I can replace pronouns with nouns!
    • but I shouldn’t for a number of reasons.
  • Main blocker: genders are still a hell of a clue.
    • maybe asking all animals to be of the same gender is a good idea :(

Onwards

  • Template changes:
    • Made it make all animals involved of the same gender
      • Doesn’t work always though
    • limited the stories to 300 words, so fewer adjectives and more content.
  • Allowed more flexible choice of context/question spans by either -1’ing for “whatever is left” or by providing a ratio of context/question span lengths.
  • Limited the given options to ones with the correct gender
  • TODO: separate make-options-agreed function to clean up the main loop
  • manually fix things like “миша”.lemma_ == “миш” by a separate function maybe.
    • done

Next up:

ERROR:ua_cbt:Верблюд же, відчуваючи полегшення, що зміг уникнути конфлікту, повернувся до своєї тіні під пальмою, де продовжив роздумувати про важливість рівноваги та справедливості у світі, де кожен шукає своє місце під сонцем.
	пальмою -> ['пустелею', 'водити', 'стороною', 'історією']

Fixed.

Fixed вОди

Верблюдиця та шакал опинилися наодинці у безкрайній пустелі, позбавлені підтримки та провізії.
        Верблюдиця -> ['Верблюдиця', 'Люда', 'Люди']

Fixed Люда 1 and 2.

cbt · Datasets at Hugging Face

Google Bard

Is quite good at generating stories if given an Ukrainian prompt!

Has trouble following the bits about number of characters, but the grammar is much better. Though can stop randomly.

https://g.co/bard/share/b410fb1181be


  1. The Magic Egg and Other Tales from Ukraine. Retold by Barbara J. Suwyn; drawings by author; edited and with an introduction by Natalie O. Kononenko., found in Ukrainian fairy tale - Wikipedia ↩︎

Nel mezzo del deserto posso dire tutto quello che voglio.