Harden AI writer response handling

This commit is contained in:
Your Name
2026-06-17 13:44:25 +05:00
parent 969ee11eed
commit 86ff75adbd
2 changed files with 23 additions and 1 deletions
@@ -0,0 +1,19 @@
UPDATE app_settings
SET value_json = to_jsonb($contract$
OUTPUT SCHEMA (return array matching input order):
{"rewrites":[{"id":123,"category_id":2,"text":"готовый текст без хэштегов","notes":"короткая заметка для редактора или null"}]}
Rules:
- Input is a JSON object with key "posts" containing accepted posts.
- Input has key "categories" with objects: id, name, tag.
- Each post includes producer_name and producer_tag. producer_name can be a manufacturer, shop, or publishing source.
- Pick exactly one category from the categories list in input and return its numeric id as category_id.
- Do not add links or hashtags to rewritten text.
- Return JSON only. No markdown. No text outside JSON.
- Never return an empty object. Never omit the "rewrites" key.
- Return one rewrite for every input post id.
- The "text" field must be a ready-to-publish Russian post with normal paragraph line breaks encoded as JSON string newlines.
- The "notes" field must be a short editor note in Russian or null.
$contract$::text),
updated_at = NOW()
WHERE key='ai_writer_contract';
+4 -1
View File
@@ -41,6 +41,7 @@ Rules:
- Pick exactly one category from the categories list in input and return its numeric id as category_id. - Pick exactly one category from the categories list in input and return its numeric id as category_id.
- Do not add links or hashtags to rewritten text. - Do not add links or hashtags to rewritten text.
- Return JSON only. No markdown. No text outside JSON. - Return JSON only. No markdown. No text outside JSON.
- Never return an empty object. Never omit the "rewrites" key.
- Return one rewrite for every input post id. - Return one rewrite for every input post id.
- The "text" field must be a ready-to-publish Russian post with normal paragraph line breaks encoded as JSON string newlines. - The "text" field must be a ready-to-publish Russian post with normal paragraph line breaks encoded as JSON string newlines.
- The "notes" field must be a short editor note in Russian or null. - The "notes" field must be a short editor note in Russian or null.
@@ -434,6 +435,8 @@ class AIWriterWorker:
for p in posts for p in posts
} }
batch_id = await self.create_batch(provider, model, prompt, payload) batch_id = await self.create_batch(provider, model, prompt, payload)
response = None
usage = None
try: try:
response, usage = await self.call_ai(provider, model, api_key, api_base, prompt, payload, temperature, timeout) response, usage = await self.call_ai(provider, model, api_key, api_base, prompt, payload, temperature, timeout)
rewrites = validate_rewrites(response, set(post_ids), categories, source_tags_by_id) rewrites = validate_rewrites(response, set(post_ids), categories, source_tags_by_id)
@@ -443,7 +446,7 @@ class AIWriterWorker:
return True return True
except Exception as exc: except Exception as exc:
await self.mark_posts_failed(post_ids, str(exc)) await self.mark_posts_failed(post_ids, str(exc))
await self.finish_batch(batch_id, "failed", error=str(exc)) await self.finish_batch(batch_id, "failed", response=response, error=str(exc), usage=usage)
logger.exception("AI writer batch failed: id={} error={}", batch_id, exc) logger.exception("AI writer batch failed: id={} error={}", batch_id, exc)
return True return True