Summaries on gpt-5.5 with strict Bosnian-only rules and a proofreading pass
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LzKpYaEsuWDevuNnvSjcFW
This commit is contained in:
@@ -28,7 +28,7 @@ journalctl --user -u idriz -f
|
||||
```
|
||||
|
||||
## Konfiguracija (okolina)
|
||||
`OPENAI_API_KEY`, `IDRIZ_REALTIME_MODEL` (gpt-realtime-2.1), `IDRIZ_TEXT_MODEL` (gpt-5.4-mini), `IDRIZ_IMAGE_MODEL` (gpt-image-2),
|
||||
`OPENAI_API_KEY`, `IDRIZ_REALTIME_MODEL` (gpt-realtime-2.1), `IDRIZ_TEXT_MODEL` (gpt-5.5), `IDRIZ_IMAGE_MODEL` (gpt-image-2),
|
||||
`IDRIZ_VOICE` (cedar), `IDRIZ_PRINTER` (idriz-printer), `IDRIZ_DRY_RUN=1` (ne štampa), `IDRIZ_MAX_PAGES` (2),
|
||||
`IDRIZ_VAD_SILENCE_MS` (900), `IDRIZ_MIC_DEVICE`, `IDRIZ_SPEAKER_DEVICE`.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ def _env(name: str, default: str) -> str:
|
||||
class Config:
|
||||
openai_api_key: str = field(default_factory=lambda: _env("OPENAI_API_KEY", ""))
|
||||
realtime_model: str = field(default_factory=lambda: _env("IDRIZ_REALTIME_MODEL", "gpt-realtime-2.1"))
|
||||
text_model: str = field(default_factory=lambda: _env("IDRIZ_TEXT_MODEL", "gpt-5.4-mini"))
|
||||
text_model: str = field(default_factory=lambda: _env("IDRIZ_TEXT_MODEL", "gpt-5.5"))
|
||||
image_model: str = field(default_factory=lambda: _env("IDRIZ_IMAGE_MODEL", "gpt-image-2"))
|
||||
transcription_model: str = field(default_factory=lambda: _env("IDRIZ_TRANSCRIPTION_MODEL", "gpt-4o-mini-transcribe"))
|
||||
voice: str = field(default_factory=lambda: _env("IDRIZ_VOICE", "cedar"))
|
||||
|
||||
@@ -17,7 +17,12 @@ Pravila:
|
||||
- Dužina: između 280 i 420 riječi. Nikako više. Ovo ide na papir sa slikom, mora biti prozračno.
|
||||
- Struktura: naslov (kratak, može i sa uzvikom), uvod od 2-3 rečenice koji odmah privuče pažnju, zatim 3 kratka poglavlja sa podnaslovima u obliku pitanja ("Kako nastaje?", "Gdje ih ima?"), po 2-4 rečenice, i na kraju "Da li si znao?" sa tačno 3 kratke crtice.
|
||||
- Piši tačno, prema članku. Ne izmišljaj podatke. Brojeve i godine zadrži.
|
||||
- Bez engleskih riječi osim imena koja se ne prevode.
|
||||
- JEZIK JE NAJVAŽNIJI: svaka riječ mora biti na bosanskom. Nikakve engleske riječi ni polu-prevedeni izrazi.
|
||||
Stručne pojmove prevedi domaćom riječju koju djeca u BiH koriste u školi (npr. "tectonic plates" → "tektonske ploče",
|
||||
"hotspot" → "vruća tačka", "mantle" → "plašt", "crust" → "kora", "species" → "vrsta", "habitat" → "stanište").
|
||||
Ako je pojam neophodno zadržati, daj ga u zagradi iza prevoda, ali samo za lična imena, nazive mjesta i naučna latinska imena.
|
||||
Nazive mjesta koristi u domaćem obliku (Island, Havaji, Sjedinjene Američke Države, Tihi okean).
|
||||
- Pazi na padeže, rod i ijekavicu (mlijeko, rijeka, cvijet, dijete). Bez srpskih i hrvatskih posebnosti kad postoji bosanska riječ.
|
||||
Odgovori ISKLJUČIVO JSON objektom oblika:
|
||||
{"naslov": "...",
|
||||
"html": "<p>uvod</p><h2>Pitanje?</h2><p>...</p>...",
|
||||
@@ -36,6 +41,27 @@ class Summary:
|
||||
image_prompt: str
|
||||
|
||||
|
||||
LEKTOR = """Ti si lektor za bosanski jezik u dječijoj izdavačkoj kući. Dobit ćeš JSON sa sažetkom za dijete.
|
||||
Vrati ISTI JSON (ista polja, ista struktura, isti HTML tagovi) ali ispravljen:
|
||||
- svaku englesku ili stranu riječ zamijeni bosanskom (osim ličnih imena, naziva mjesta i latinskih naučnih naziva u zagradi),
|
||||
- ispravi gramatiku, padeže, rod i ijekavicu,
|
||||
- rečenice zadrži kratke i razumljive djetetu, ne dodaj novi sadržaj i ne mijenjaj činjenice.
|
||||
Odgovori isključivo JSON objektom."""
|
||||
|
||||
|
||||
async def proofread(client: AsyncOpenAI, model: str, data: dict) -> dict:
|
||||
resp = await client.chat.completions.create(
|
||||
model=model,
|
||||
messages=[{"role": "system", "content": LEKTOR}, {"role": "user", "content": json.dumps(data, ensure_ascii=False)}],
|
||||
response_format={"type": "json_object"},
|
||||
)
|
||||
try:
|
||||
fixed = json.loads(resp.choices[0].message.content or "{}")
|
||||
except json.JSONDecodeError:
|
||||
return data
|
||||
return fixed if fixed.get("html") and fixed.get("naslov") else data
|
||||
|
||||
|
||||
async def summarize(client: AsyncOpenAI, model: str, article: Article, topic: str, age: str) -> Summary:
|
||||
user = (
|
||||
f"Tema koju je dijete tražilo: {topic}\n"
|
||||
@@ -48,6 +74,10 @@ async def summarize(client: AsyncOpenAI, model: str, article: Article, topic: st
|
||||
response_format={"type": "json_object"},
|
||||
)
|
||||
data = json.loads(resp.choices[0].message.content or "{}")
|
||||
try:
|
||||
data = await proofread(client, model, data)
|
||||
except Exception: # noqa: BLE001
|
||||
log.exception("lektorski prolaz nije uspio, koristim prvu verziju")
|
||||
s = Summary(
|
||||
title=data.get("naslov") or article.title,
|
||||
html=data.get("html") or "<p>Nažalost, nisam uspio napisati sažetak.</p>",
|
||||
|
||||
Reference in New Issue
Block a user