diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-21 10:01:54 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-21 10:01:54 +0300 |
| commit | 6c884da0cbe65689bf089951cb5e621d121416e6 (patch) | |
| tree | ad162164a9ed4f9c8e7cd9b6cb5c004e9e28bd9b | |
| parent | 6bc865e5a70c31060d8ff49aec7d690593733c3c (diff) | |
Fix output paths and language-neutral prompts
| -rw-r--r-- | internal/comic/artist.go | 12 | ||||
| -rw-r--r-- | internal/comic/comic_test.go | 16 | ||||
| -rw-r--r-- | internal/comic/localization.go | 10 | ||||
| -rw-r--r-- | internal/comic/runner.go | 10 | ||||
| -rw-r--r-- | internal/config/config_test.go | 2 | ||||
| -rw-r--r-- | prompts/back_cover_prompt.md | 20 | ||||
| -rw-r--r-- | prompts/bible_system.md | 8 | ||||
| -rw-r--r-- | prompts/cover_prompt.md | 28 | ||||
| -rw-r--r-- | prompts/gallery_page_prompt.md | 16 | ||||
| -rw-r--r-- | prompts/panel_script_prompt.md | 19 | ||||
| -rw-r--r-- | prompts/rendering_requirement.md | 12 | ||||
| -rw-r--r-- | prompts/rendering_requirement_end.md | 2 | ||||
| -rw-r--r-- | prompts/story_full_prompt.md | 57 | ||||
| -rw-r--r-- | prompts/story_page_prompt.md | 36 | ||||
| -rw-r--r-- | prompts/story_prompt.md | 10 | ||||
| -rw-r--r-- | prompts/story_system.md | 4 |
16 files changed, 133 insertions, 129 deletions
diff --git a/internal/comic/artist.go b/internal/comic/artist.go index 65fed3d..fd5dc60 100644 --- a/internal/comic/artist.go +++ b/internal/comic/artist.go @@ -360,12 +360,12 @@ func pageScriptForPage(panelScript [][]string, idx int) []string { func buildPanelLayout(section string, pagePanels []string) string { if len(pagePanels) == 4 && pagePanels[0] != "" && pagePanels[1] != "" && pagePanels[2] != "" && pagePanels[3] != "" { var sb strings.Builder - sb.WriteString("Раздели изображението точно на 4 различни панела в решетка 2×2. Панелите трябва да разказват сцената последователно и да останат ясно различни един от друг.\n") + sb.WriteString("Divide the image into exactly 4 distinct panels in a 2x2 grid. The panels must tell the scene in sequence and remain visually distinct from each other.\n") for i, panel := range pagePanels { if panel == "" { continue } - fmt.Fprintf(&sb, "Панел %d: %s\n", i+1, panel) + fmt.Fprintf(&sb, "Panel %d: %s\n", i+1, panel) } return sb.String() } @@ -378,15 +378,15 @@ func buildPanelLayout(section string, pagePanels []string) string { } excerpt += "…" } - return "Раздели изображението точно на 4 различни панела в решетка 2×2. Панелите трябва да разказват историята последователно от начало към край и да останат ясно различни.\n" + - "Откъс от историята:\n\n" + excerpt + "\n" + return "Divide the image into exactly 4 distinct panels in a 2x2 grid. The panels must tell the story in sequence from beginning to end and remain visually distinct.\n" + + "Story excerpt:\n\n" + excerpt + "\n" } func blurbBoxInstruction(blurb string) string { if strings.TrimSpace(blurb) == "" { - return "правоъгълно текстово поле (бял или кремав фон, тънка черна рамка) близо до дъното, в стил на класически синопсис на задната корица" + return "a rectangular text box near the bottom with a white or cream background and a thin black border, styled like a classic back-cover synopsis box" } - return fmt.Sprintf("правоъгълно текстово поле (бял или кремав фон, тънка черна рамка) близо до дъното, което показва този текст в курсив:\n %q", blurb) + return fmt.Sprintf("a rectangular text box near the bottom with a white or cream background and a thin black border, displaying this italic text:\n %q", blurb) } func errorsJoin(errs ...error) error { diff --git a/internal/comic/comic_test.go b/internal/comic/comic_test.go index 319c7b2..b1ea5ab 100644 --- a/internal/comic/comic_test.go +++ b/internal/comic/comic_test.go @@ -47,11 +47,25 @@ func TestBuildPanelLayoutUsesFallbackExcerpt(t *testing.T) { t.Parallel() got := buildPanelLayout("one two three four five", nil) - if !strings.Contains(got, "Откъс от историята") { + if !strings.Contains(got, "Story excerpt") { t.Fatalf("buildPanelLayout() = %q", got) } } +func TestComicOutputDirDoesNotDuplicateComicsSegment(t *testing.T) { + t.Parallel() + + if got, want := comicOutputDir("comics", "slug"), filepath.Join("comics", "slug"); got != want { + t.Fatalf("comicOutputDir() = %q, want %q", got, want) + } + if got, want := comicOutputDir(".", "slug"), filepath.Join(".", "comics", "slug"); got != want { + t.Fatalf("comicOutputDir() = %q, want %q", got, want) + } + if got, want := comicOutputDir("/tmp/out", "slug"), filepath.Join("/tmp/out", "comics", "slug"); got != want { + t.Fatalf("comicOutputDir() = %q, want %q", got, want) + } +} + func TestCopyGalleryPNGsToComicsGallery(t *testing.T) { t.Parallel() diff --git a/internal/comic/localization.go b/internal/comic/localization.go index 6eb2a0d..941e741 100644 --- a/internal/comic/localization.go +++ b/internal/comic/localization.go @@ -13,9 +13,9 @@ func localizedBrandName(language, script string) string { func localizedScriptName(script string) string { switch { case strings.EqualFold(script, "Cyrillic"): - return "кирилица" + return "Cyrillic" case strings.EqualFold(script, "Latin"): - return "латиница" + return "Latin" default: return script } @@ -27,11 +27,11 @@ func localizedLanguageName(language, script string) string { } switch { case strings.EqualFold(language, "English"): - return "английски" + return "English" case strings.EqualFold(language, "German"): - return "немски" + return "German" case strings.EqualFold(language, "French"): - return "френски" + return "French" default: return language } diff --git a/internal/comic/runner.go b/internal/comic/runner.go index 5843aab..00275b8 100644 --- a/internal/comic/runner.go +++ b/internal/comic/runner.go @@ -128,7 +128,7 @@ func (r *Runner) Run(ctx context.Context, batchFile string) error { fmt.Printf(" Comic title: %q (slug: %s)\n", result.Title, slug) } - comicsDir := filepath.Join(dir, "comics", slug) + comicsDir := comicOutputDir(dir, slug) if err := os.MkdirAll(comicsDir, 0o755); err != nil { return fmt.Errorf("create comics dir %s: %w", comicsDir, err) } @@ -171,6 +171,14 @@ func (r *Runner) Run(ctx context.Context, batchFile string) error { return r.handleNarration(ctx, result.StoryText, slug, comicsDir) } +func comicOutputDir(outputRoot, slug string) string { + root := orDefault(outputRoot, ".") + if filepath.Base(filepath.Clean(root)) == "comics" { + return filepath.Join(root, slug) + } + return filepath.Join(root, "comics", slug) +} + var _ StoryRunner = (*Runner)(nil) func (r *Runner) handleNarration(ctx context.Context, storyText, titleSlug, dir string) error { diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 4f6021d..4a3f51a 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -95,7 +95,7 @@ func TestRenderPromptFallsBackToEmbeddedTemplate(t *testing.T) { if err != nil { t.Fatalf("RenderPrompt() error = %v", err) } - if !strings.Contains(got, "Напиши история с дължина около 250 думи на български") { + if !strings.Contains(got, "Write a story of about 250 words in български") { t.Fatalf("RenderPrompt() = %q, want embedded story prompt", got) } } diff --git a/prompts/back_cover_prompt.md b/prompts/back_cover_prompt.md index 5e54668..79dd012 100644 --- a/prompts/back_cover_prompt.md +++ b/prompts/back_cover_prompt.md @@ -1,15 +1,15 @@ -{{if .Language}}Български комикс. Всички видими надписи, ленти и етикети на задната корица са на {{.ScriptName}}. Без латиница на задната корица. +This is a {{.LanguageName}} comic. All visible back-cover text, banners, boxes, and labels must use {{.ScriptName}} script only. -{{end}}Стил: {{.Style}}.{{.RenderingRequirement}} -Пълна задна корица {{if .RenderingRequirement}}фотографска сцена{{else}}илюстрация{{end}} в пейзажен формат 16:9. -Без панелна решетка. Без балони за реплики. -{{if .Bible}}РЕФЕРЕНЦИЯ ЗА ПЕРСОНАЖИТЕ И СРЕДАТА: +Style: {{.Style}}.{{.RenderingRequirement}} +Full back cover {{if .RenderingRequirement}}photographic scene{{else}}illustration{{end}} in landscape 16:9 format. +No panel grid. No speech bubbles. +{{if .Bible}}CHARACTER AND SETTING REFERENCE: {{.Bible}} -{{end}}Правила за композицията: - • ОСНОВНА СЦЕНА: спокойно, топло и завършено изображение в горните 60% на корицата — ТОЧНО описаните герои от историята в мирен или триумфален финален момент, с цялата среда зад тях. Сцената трябва да изглежда фотографска, не рисувана. - • ТЕКСТОВО ПОЛЕ: {{.BlurbBox}} - • ДОЛНА ЛЕНТА: поле с баркод долу вляво, заглавие на поредицата „{{.SeriesTitle}}“ долу вдясно — класическо комиксово оформление. -ВАЖНО: на задната корица могат да присъстват само героите, посочени в референцията. Същата възраст, лице и дрехи като в страниците. Всички надписи са на {{.ScriptName}}. Подсказка за финала на историята: +{{end}}Composition rules: + • MAIN ART: a calm, warm, resolved image in the upper 60% of the cover — EXACTLY the characters described in the reference in a peaceful or triumphant final moment, with the full setting behind them. + • TEXT BOX: {{.BlurbBox}} + • BOTTOM STRIP: barcode box at bottom-left, series title "{{.SeriesTitle}}" at bottom-right — classic comic back-cover layout. +IMPORTANT: only characters named in the reference may appear. Same age, face, clothing, and animal companions as in the interior pages. All visible text must use {{.LanguageName}} and {{.ScriptName}} script only. Story ending hint: {{.StoryText}}{{if .RenderingRequirement}}{{.RenderingRequirementEnd}}{{end}} diff --git a/prompts/bible_system.md b/prompts/bible_system.md index 63901b4..852e588 100644 --- a/prompts/bible_system.md +++ b/prompts/bible_system.md @@ -1,10 +1,10 @@ You are a comic-book art director producing a CHARACTER CONSISTENCY GUIDE in {{.LanguageName}} using {{.ScriptName}} script for an illustrator. -Use only {{.ScriptName}}. Do not use Latin letters anywhere in the guide. If a name or term is foreign, transliterate it into {{.ScriptName}}. +Use only {{.LanguageName}} and {{.ScriptName}} script. Do not mix languages or scripts. If a name or term is foreign, adapt it consistently. -For every named HUMAN character provide: name, apparent age category (young child, teenager, young adult, middle-aged, elderly), hair (colour + style), eye colour, skin tone, build, and the EXACT clothing they wear — specify garment, colour, pattern, and fit. The character's apparent age MUST NOT change across any panel, page, cover, or back cover — they must always look the same. Clothing must NOT change between panels unless the story explicitly describes a change; if no change is described, list the same outfit for all appearances. +For every named HUMAN character provide: name, adult age category, hair (colour + style), eye colour, skin tone, build, and the EXACT clothing they wear — specify garment, colour, pattern, and fit. The character's apparent age MUST NOT change across any panel, page, cover, or back cover. Clothing must NOT change between panels unless the story explicitly describes a change; if no change is described, list the same outfit for all appearances. -For every named ANIMAL character provide: name, species, exact breed, fur/feather/scale colour and pattern, eye colour, size, any distinctive markings, and typical body posture. The animal must look IDENTICAL on every page — same breed, same markings, same eye colour. Do NOT substitute a generic animal; if the story says Persian cat, every panel must show a Persian cat with the exact described colouring. +For every named ANIMAL character provide: name, species, exact breed, fur/feather/scale colour and pattern, eye colour, size, any distinctive markings, and typical body posture. The animal must look IDENTICAL on every page — same breed, same markings, same eye colour. Do NOT substitute a generic animal. Also describe: the setting (location, time of day, weather, key props) and overall lighting / colour mood. -Be extremely specific — this guide will be copy-pasted into every panel prompt to lock visual consistency. Maximum 300 words. No headers, just dense descriptive prose. +Be extremely specific — this guide will be copied into every panel prompt to lock visual consistency. Maximum 300 words. No headers, just dense descriptive prose. diff --git a/prompts/cover_prompt.md b/prompts/cover_prompt.md index 66a92fd..c9fcb2f 100644 --- a/prompts/cover_prompt.md +++ b/prompts/cover_prompt.md @@ -1,19 +1,19 @@ -{{if .Language}}Български комикс. Всички надписи на корицата са на {{.ScriptName}}, включително основното заглавие. +This is a {{.LanguageName}} comic. All visible cover text, including the main title, must use {{.ScriptName}} script only. -{{end}}Стил: {{.Style}}.{{.RenderingRequirement}} -Пълна предна корица {{if .RenderingRequirement}}фотографска сцена{{else}}илюстрация{{end}} в пейзажен формат 16:9. -Без панелна решетка. Без балони за реплики. -{{if .Bible}}РЕФЕРЕНЦИЯ ЗА ПЕРСОНАЖИТЕ И СРЕДАТА: +Style: {{.Style}}.{{.RenderingRequirement}} +Full front cover {{if .RenderingRequirement}}photographic scene{{else}}illustration{{end}} in landscape 16:9 format. +No panel grid. No speech bubbles. +{{if .Bible}}CHARACTER AND SETTING REFERENCE: {{.Bible}} -{{end}}ОСНОВНО ЗАГЛАВИЕ — най-важният визуален елемент на корицата: - • Измисли драматично, специфично за историята комиксово заглавие, което подхожда на героите и темата на откъса по-долу. Заглавието трябва да е огромно, доминиращо и разположено в самия връх на корицата. - • Под основното заглавие добави по-малка лента с подзаглавие „{{.Subtitle}}“ в контрастен цвят. - • Добави малка кръгла или звездовидна значка в горния ляв ъгъл, свързана с темата на историята. -Останали правила за композицията: - • ОСНОВНА СЦЕНА: под заглавието — драматична {{if .RenderingRequirement}}фотографска кинематографична сцена{{else}}илюстрация{{end}} с ТОЧНО описаните герои от историята — същите лица, възраст, дрехи и животни. Не измисляй нови персонажи и не използвай заместители. - • КОРОВИ ФРАЗИ: 2–3 кратки фрази на {{.LanguageName}} в удебелен дисплей шрифт. - • ДОЛНА ЛЕНТА: поле за цена долу вляво, номер на брой долу вдясно — класическо комиксово оформление. -ВАЖНО: на корицата могат да присъстват само героите, посочени в референцията. Същата възраст, лице и дрехи като в страниците. Всички надписи са на {{.ScriptName}}. Откъс от историята: +{{end}}MAIN TITLE — the most important visual element on the cover: + • Invent a dramatic, story-specific comic title that fits the characters and theme of the story excerpt below. The title must be huge, dominant, and placed at the very top of the cover. + • Directly below the main title, add a smaller subtitle banner: "{{.Subtitle}}" in a contrasting colour. + • Add a small circular or star-shaped badge in the upper-left corner related to the story theme. +Composition rules: + • MAIN ART: below the title, a dramatic {{if .RenderingRequirement}}photographic cinematic scene{{else}}illustration{{end}} with EXACTLY the characters described in the reference — same faces, ages, clothing, and animals. Do not invent new characters or use substitutes. + • COVER LINES: 2-3 short teaser phrases in {{.LanguageName}} using {{.ScriptName}} script in bold display type. + • BOTTOM STRIP: price box at bottom-left, issue number at bottom-right — classic comic cover layout. +IMPORTANT: only characters named in the reference may appear. Same age, face, clothing, and animal companions as in the interior pages. All visible text must use {{.LanguageName}} and {{.ScriptName}} script only. Story excerpt: {{.StoryText}}{{if .RenderingRequirement}}{{.RenderingRequirementEnd}}{{end}} diff --git a/prompts/gallery_page_prompt.md b/prompts/gallery_page_prompt.md index 8713bbe..9aaf8ab 100644 --- a/prompts/gallery_page_prompt.md +++ b/prompts/gallery_page_prompt.md @@ -1,13 +1,13 @@ -Стил: {{.Style}}.{{.RenderingRequirement}} -Един цял кадър {{if .RenderingRequirement}}фотография — да изглежда 100% като реален кадър от камера{{else}}илюстрация{{end}} с пейзажен формат 16:9. -Не разделяй изображението на няколко панела или секции. Цялото поле трябва да е една единствена сцена. -Без текст от какъвто и да е вид. Без заглавие, етикети, балони за реплики, граници на панели или интерфейсни елементи. -{{if .Bible}}РЕФЕРЕНЦИЯ ЗА ПЕРСОНАЖИТЕ И СРЕДАТА: +Style: {{.Style}}.{{.RenderingRequirement}} +One full-frame {{if .RenderingRequirement}}photograph that looks 100% like a real camera shot{{else}}illustration{{end}} in landscape 16:9 format. +Do not split the image into panels or sections. The entire canvas is one single scene. +No text of any kind. No title, labels, speech bubbles, panel borders, or UI elements. +{{if .Bible}}CHARACTER AND SETTING REFERENCE: {{.Bible}} {{end}} -Композиция: {{.Pose}} +Composition: {{.Pose}} -Героите трябва да са ТОЧНО описаните персонажи — същите лица, пол, възраст и дрехи. Ако има естествен спътник-животно, включи го. Не измисляй нови персонажи и не променяй пола им. Не добавяй текстови наслагвания. -Фон: средата на историята, предадена с пълна кинематографична атмосфера и цветово настроение.{{if .RenderingRequirement}}{{.RenderingRequirementEnd}}{{end}} +The characters must be EXACTLY the described people — same faces, gender, adult age, and clothing. Include the animal companion if naturally present. Do not invent new characters or change anyone's gender. Do not add text overlays. +Background: the story setting rendered with full cinematic atmosphere and colour mood.{{if .RenderingRequirement}}{{.RenderingRequirementEnd}}{{end}} diff --git a/prompts/panel_script_prompt.md b/prompts/panel_script_prompt.md index 88f3350..f9da735 100644 --- a/prompts/panel_script_prompt.md +++ b/prompts/panel_script_prompt.md @@ -1,12 +1,7 @@ -Напиши точно 20 визуални описания на панели за комиксовия илюстратор, по един ред, в строг хронологичен ред на историята. -Форматът на всеки ред трябва да е точно: P{page}-{panel}: {описание} -където page е от 1 до 5, а panel е A (горе вляво), B (горе вдясно), C (долу вляво), D (долу вдясно). -Всяко описание е от 1 до 2 изречения и трябва да включва: КОЙ е в панела, КАКВО прави, КЪДЕ се намира, какво е изражението или езикът на тялото му, и - ЗАДЪЛЖИТЕЛНО за повечето панели - точния диалог или мисъл на {{.LanguageName}}, написан в кавички. -Поне 3 от 4-те панела на всяка страница ТРЯБВА да включват диалог или мисъл на {{.LanguageName}} в балон за реплика или мисъл. Диалогът трябва да идва директно от историята и да е на {{.ScriptName}}. -20-те панела трябва да преразкажат историята от началото до края - всяка страница покрива един етап, всеки панел придвижва действието напред. -Не повтаряй една и съща сцена или ъгъл на камерата в последователни панели. -Примерен формат, замени с истинското съдържание на историята: -P1-A: Мария излиза от входната си врата в утринната светлина, с чанта на рамо, и казва "Най-сетне!" в балон за реплика. -P1-B: Тя върви по оживена улица покрай паркирани коли, с слушалки в ушите, и мисли "Толкова хубав ден." в балон за мисъл. -P1-C: Крупен план на ръката ѝ, която стиска голяма пареща чаша кафе, а баристата ѝ я подава с думите "Заповядайте!" в балон за реплика. -P1-D: Мария спира при входа на парк и поглежда към зелените дървета отпред, като казва "Точно това ми трябваше." в балон за реплика. +Write exactly 20 visual panel descriptions for the comic illustrator, one per line, in strict chronological story order. +Each line must use exactly this format: P{page}-{panel}: {description} +where page is 1 through 5, and panel is A (top-left), B (top-right), C (bottom-left), or D (bottom-right). +Each description must be 1-2 sentences and include who is in the panel, what they do, where they are, their expression or body language, and, for most panels, exact dialogue or thought text in {{.LanguageName}} inside quotation marks. +At least 3 of the 4 panels on every page MUST include dialogue or thought text in {{.LanguageName}} for a speech or thought bubble. Dialogue must come directly from the story and use {{.ScriptName}} script. +The 20 panels must retell the story from beginning to end; each page covers one stage and each panel moves the action forward. +Do not repeat the same scene or camera angle in consecutive panels. diff --git a/prompts/rendering_requirement.md b/prompts/rendering_requirement.md index 8b6f312..f2a4f53 100644 --- a/prompts/rendering_requirement.md +++ b/prompts/rendering_requirement.md @@ -1,6 +1,6 @@ -ФОТОРЕАЛИСТИЧЕН РЕЖИМ за това изображение: - • Картината трябва да изглежда като истинска фотография или кадър от високобюджетен жив филм. - • Кожата, косата, платът, металът и средата трябва да изглеждат естествени и реални, без рисуван или живописен ефект. - • Избягвай карикатурен, аниме, манга, комиксов или очевидно илюстративен вид. - • Текстови елементи, ако са нужни по композиция, трябва да изглеждат като част от фотографска корица или плакат. - • При галерийни кадри цялото изображение трябва да е изцяло фотографско. +ULTRA-REALISTIC MODE for this image: + • The image must look like a real photograph or a frame from a high-budget live-action film. + • Skin, hair, fabric, metal, and environments must look natural and real, with no drawn or painterly effect. + • Avoid cartoon, anime, manga, comic-line-art, or obviously illustrated rendering. + • Text elements, if required by the composition, should look like part of a photographed physical cover, sign, or poster. + • For gallery images, the whole image must be entirely photographic. diff --git a/prompts/rendering_requirement_end.md b/prompts/rendering_requirement_end.md index 36aa8cd..4e92c88 100644 --- a/prompts/rendering_requirement_end.md +++ b/prompts/rendering_requirement_end.md @@ -1 +1 @@ -КРАЕН ЗАКЛЮЧИТЕЛЕН РЕЖИМ — ФОТОРЕАЛИЗЪМ: цялото изображение трябва да изглежда като заснето с камера. Ако нещо изглежда рисувано, резултатът е грешен. Не допускай комиксов вид между панелите или в галерийните кадри. +FINAL STYLE LOCK — PHOTOREALISM: the entire image must look camera-captured. If anything looks drawn or painted, the result is wrong. Do not drift toward comic art between panels or in gallery images. diff --git a/prompts/story_full_prompt.md b/prompts/story_full_prompt.md index 1b5b4e9..e170d99 100644 --- a/prompts/story_full_prompt.md +++ b/prompts/story_full_prompt.md @@ -1,46 +1,33 @@ -Напиши история с дължина около 250 думи на {{.LanguageName}}, която естествено използва всички следните думи. -Историята трябва да е {{.Genre}} — не пиши безлична приказка. -Използвай само {{.ScriptName}}. Не използвай латиница никъде в текста. Ако чуждо име или термин е нужен, транслитерирай го в {{.ScriptName}}. -Използвай всяка дума естествено, но не повтаряй списъка с думи, булетите или етикетите в текста на историята. +Write a story of about 250 words in {{.LanguageName}} that naturally uses all of the following words. +The story must be {{.Genre}}; do not write a generic fairy tale. +Use {{.ScriptName}} script only and do not mix in another language or script. +Use every word naturally, but do not repeat the word list, bullet points, labels, or prompt instructions in the story. -Думи за включване: +Words to include: {{.Words}} -След текста на историята напиши точно този ред самостоятелно (без нищо друго на този ред): +After the story text, write exactly this separator line by itself: {{.StoryBibleSeparator}} -След това напиши РЪКОВОДСТВО ЗА ПОСЛЕДОВАТЕЛНОСТТА НА ПЕРСОНАЖИТЕ на {{.LanguageName}} с {{.ScriptName}} за илюстратор. -ВАЖНО: всички човешки персонажи трябва да са възрастни (18+). Не описвай никой като дете, тийнейджър или непълнолетен. -За всеки именуван ЧОВЕШКИ персонаж: име, приблизителна възраст като млад възрастен или по-възрастен, коса (цвят + стил), цвят на очите, тон на кожата, телосложение и ТОЧНО облекло (дреха, цвят, шарка, кройка). Приблизителната възраст и облеклото не трябва да се променят — запиши същото за всички появи. -За всеки именуван ЖИВОТИНСКИ персонаж: име, вид, точна порода, цвят и шарка на козината/перата/люспите, цвят на очите, размер, отличителни белези и типична стойка на тялото. Животното трябва да изглежда ИДЕНТИЧНО във всяка част — същата порода, същите белези, същия цвят на очите. -Добави още: среда (място, време на деня, време, ключови реквизити) и общо осветление/цветово настроение. -Максимум 280 думи за ръководството. Без заглавия, само плътен текст. +Then write a CHARACTER CONSISTENCY GUIDE in {{.LanguageName}} using {{.ScriptName}} script for an illustrator. +IMPORTANT: all human characters must be adults (18+). Do not describe anyone as a child, teenager, or minor. +For every named HUMAN character: name, approximate adult age, hair (colour + style), eye colour, skin tone, build, and EXACT clothing (garment, colour, pattern, fit). Apparent age and clothing must stay the same for all appearances. +For every named ANIMAL character: name, species, exact breed, fur/feather/scale colour and pattern, eye colour, size, distinctive markings, and typical body posture. The animal must look IDENTICAL everywhere. +Also describe: setting (location, time of day, weather, key props) and overall lighting/colour mood. +Maximum 280 words for the guide. No headers, just dense descriptive prose. -След ръководството напиши точно този ред самостоятелно: +After the guide, write exactly this separator line by itself: {{.StoryTitleSeparator}} -След това напиши кратко комиксово заглавие на {{.LanguageName}} с {{.ScriptName}}: 2-4 думи, които улавят темата и персонажите на историята. Изведи само заглавието — без кавички, без пунктуация, без обяснение. +Then write a short comic title in {{.LanguageName}} using {{.ScriptName}} script: 2-4 words that capture the story's theme and characters. Output only the title: no quotes, punctuation, or explanation. -След заглавието напиши точно този ред самостоятелно: +After the title, write exactly this separator line by itself: {{.StoryPanelSeparator}} -Напиши точно 20 визуални описания на панели за комиксовия илюстратор, по един ред, в строг хронологичен ред. -Форматът на всеки ред трябва да е точно: P{page}-{panel}: {описание} -където page е от 1 до 5, а panel е A (горе вляво), B (горе вдясно), C (долу вляво), D (долу вдясно). -Всяко описание е от 1 до 2 изречения и трябва да включва: КОЙ е в панела, КАКВО прави, КЪДЕ се намира, какво е изражението или езикът на тялото му, и - ЗАДЪЛЖИТЕЛНО за повечето панели - точния диалог или мисъл на {{.LanguageName}}, написан в кавички. -Поне 3 от 4-те панела на всяка страница ТРЯБВА да включват диалог или мисъл на {{.LanguageName}} в балон за реплика или мисъл. Диалогът трябва да идва директно от историята и да е на {{.ScriptName}}. -20-те панела трябва да преразкажат историята от началото до края - всяка страница покрива един етап, всеки панел придвижва действието напред. -Не повтаряй една и съща сцена или ъгъл на камерата в последователни панели. -Примерен формат, замени с истинското съдържание на историята: -P1-A: Мария излиза от входната си врата в утринната светлина, с чанта на рамо, и казва "Най-сетне!" в балон за реплика. -P1-B: Тя върви по оживена улица покрай паркирани коли, с слушалки в ушите, и мисли "Толкова хубав ден." в балон за мисъл. -P1-C: Крупен план на ръката ѝ, която стиска голяма пареща чаша кафе, а баристата ѝ я подава с думите "Заповядайте!" в балон за реплика. -P1-D: Мария спира при входа на парк и поглежда към зелените дървета отпред, като казва "Точно това ми трябваше." в балон за реплика. - ---- -Напиши история с дължина около 250 думи на {{.LanguageName}}, която естествено използва всички следните думи. -Историята трябва да е {{.Genre}} — не пиши безлична приказка. -Използвай всяка дума естествено, но не повтаряй списъка с думи, булетите или етикетите в текста. Върни САМО текста на историята — без заглавие, без заглавен ред, без обяснение. - -Думи за включване: -{{.Words}} +Write exactly 20 visual panel descriptions for the comic illustrator, one per line, in strict chronological story order. +Each line must use exactly this format: P{page}-{panel}: {description} +where page is 1 through 5, and panel is A (top-left), B (top-right), C (bottom-left), or D (bottom-right). +Each description must be 1-2 sentences and include who is in the panel, what they do, where they are, their expression or body language, and, for most panels, exact dialogue or thought text in {{.LanguageName}} inside quotation marks. +At least 3 of the 4 panels on every page MUST include dialogue or thought text in {{.LanguageName}} for a speech or thought bubble. Dialogue must come from the story and use {{.ScriptName}} script. +The 20 panels must retell the story from beginning to end; each page covers one stage and each panel moves the action forward. +Do not repeat the same scene or camera angle in consecutive panels. diff --git a/prompts/story_page_prompt.md b/prompts/story_page_prompt.md index 1744fa6..6a2d787 100644 --- a/prompts/story_page_prompt.md +++ b/prompts/story_page_prompt.md @@ -1,22 +1,22 @@ -{{if .Language}}Български комикс: всички реплики, мисли, надписи и етикети в панелите трябва да са изцяло на {{.ScriptName}}. Без латиница в самите панели. +This is a {{.LanguageName}} comic page. All speech, thoughts, captions, and labels inside panels must use {{.ScriptName}} script only. -{{end}}{{.Words}} -Стил: {{.Style}}.{{.RenderingRequirement}} -Сцена за тази част от комикса. -{{if .Bible}}РЕФЕРЕНЦИЯ ЗА ПЕРСОНАЖИТЕ И СРЕДАТА: +{{.Words}} +Style: {{.Style}}.{{.RenderingRequirement}} +Interior story page only. Do NOT render a cover masthead, title banner, subtitle, price box, issue number, date, page header, page footer, logo bug, or publisher badge. +{{if .Bible}}CHARACTER AND SETTING REFERENCE: {{.Bible}} -{{end}}{{.PanelLayout}}Всеки панел е разделен с тънка черна линия. И 4-те панела трябва да са ясно различни сцени, а не едно непрекъснато изображение. Цялата площ трябва да бъде запълнена, без празни полета. -ЗАДЪЛЖИТЕЛНИ БАЛОНИ С РЕПЛИКИ — това е комикс; героите трябва да говорят: - • Най-малко 3 от 4-те панела на тази сцена трябва да имат балон с реплика или мисъл. - • Ако описанието на панела включва цитирана реплика, изобрази я точно в балона. - • Балоните за реплики са бели с черен контур и опашка към говорещия. - • Балоните за мисли са облакоподобни с малки кръгчета към мислещия. - • Всички текстове в балоните са само на {{.ScriptName}}. -ВАРИАТИВНОСТ — всеки панел трябва да се различава от останалите поне по 3 от следните измерения: ъгъл на камерата (крупен, среден, общ, от птичи поглед, нисък), поза или действие на героя, място или детайл от фона, осветление или време на деня, и предмети на преден план. Повтарянето на една и съща композиция е забранено. -{{.RenderingRequirement}}СТРОГИ ПРАВИЛА ЗА КОНСИСТЕНТНОСТ — за всеки панел: - • Човешките герои: идентични лице, възрастово внушение, прическа и облекло спрямо референцията. - • Животните: идентична порода, козина/шарка и цвят на очите — без замяна с друго животно. - • Смяна на дрехи само ако изрично е описана в сцената. - • Всички реплики, мисли и надписи са само на {{.ScriptName}}. +{{end}}{{.PanelLayout}}Each panel is separated by a thin black gutter line. All 4 panels must be clearly distinct scenes, not one continuous image. Fill the full image area with the 4 panels. +MANDATORY SPEECH BUBBLES — this is a comic; characters must speak: + • At least 3 of the 4 panels on this page must contain a speech bubble or thought bubble. + • If the panel description includes quoted dialogue, render it exactly inside the bubble. + • Speech bubbles have a white background, black outline, and a tail pointing to the speaker. + • Thought bubbles use a cloud shape with small circles leading to the thinker. + • All bubble text must use {{.LanguageName}} and {{.ScriptName}} script only. +VARIETY — every panel must differ from the others in at least 3 of these dimensions: camera angle, character pose/action, location/background detail, lighting/time of day, and foreground objects. Do not repeat the same composition. +{{.RenderingRequirement}}STRICT CONSISTENCY RULES — for every panel: + • Human characters: identical face, apparent age, hair, and clothing compared to the reference. + • Animals: identical species/breed, fur pattern, markings, and eye colour. + • Clothing changes only if this page explicitly describes a change. + • All visible text must use {{.LanguageName}} and {{.ScriptName}} script only. {{if .RenderingRequirement}}{{.RenderingRequirementEnd}}{{end}} diff --git a/prompts/story_prompt.md b/prompts/story_prompt.md index 41033b0..1ec1ae5 100644 --- a/prompts/story_prompt.md +++ b/prompts/story_prompt.md @@ -1,7 +1,7 @@ -Напиши история с дължина около 250 думи на {{.LanguageName}}, която естествено използва всички следните думи. -Историята трябва да е {{.Genre}} — не пиши безлична приказка. -Използвай само {{.ScriptName}}. Не използвай латиница никъде в текста. Ако чуждо име или термин е нужен, транслитерирай го в {{.ScriptName}}. -Използвай всяка дума естествено, но не повтаряй списъка с думи, булетите или етикетите в текста на историята. Върни САМО текста на историята — без заглавие, без заглавен ред, без обяснение. +Write a story of about 250 words in {{.LanguageName}} using all of the following words naturally. +The story must be {{.Genre}}; do not write a generic fairy tale. +Use {{.ScriptName}} script only and |
