Patryk Studzinski commited on
Commit
0dfa1e4
·
1 Parent(s): 2de7977

Improve infill prompt and add fallback for non-JSON model outputs

Browse files
Files changed (2) hide show
  1. app/domains/cars/prompts.py +14 -30
  2. app/main.py +30 -1
app/domains/cars/prompts.py CHANGED
@@ -34,8 +34,7 @@ Na podstawie poniższych danych, utwórz krótki, atrakcyjny opis marketingowy t
34
  def create_infill_prompt(text_with_gaps: str, options: InfillOptions) -> list[dict]:
35
  """
36
  Creates the chat prompt for gap-filling in car ads.
37
-
38
- The LLM must return strict JSON with filled text and per-gap choices.
39
 
40
  Args:
41
  text_with_gaps: Ad text with [GAP:n] markers
@@ -47,41 +46,26 @@ def create_infill_prompt(text_with_gaps: str, options: InfillOptions) -> list[di
47
  lang_instruction = "po polsku" if options.language == "pl" else "in English"
48
 
49
  system_content = f"""Jesteś ekspertem od uzupełniania tekstów ogłoszeń samochodowych.
 
50
 
51
- ZADANIE:
52
- Uzupełnij WSZYSTKIE luki oznaczone jako [GAP:n] naturalnymi słowami {lang_instruction}.
53
- Każda luka powinna być uzupełniona słowem lub krótką frazą (1-4 słowa).
54
 
55
- ZASADY:
56
- 1. WAŻNE: Rzeczywiście uzupełnij luki - nie zwracaj tekstu z [GAP:n] w filled_text!
57
- 2. Uzupełnienia muszą pasować kontekstowo I gramatycznie
58
- 3. Używaj słownictwa typowego dla ogłoszeń motoryzacyjnych
59
- 4. Dla każdej luki podaj {options.top_n_per_gap} alternatywne propozycje
60
 
61
- GRAMATYKA POLSKA - BARDZO WAŻNE:
62
- - Uzupełnienia MUSZĄ być w odpowiednim przypadku gramatycznym (deklinacja)!
63
- - "w kolorze [GAP:1]" uzupełnij MIEJSCOWNIKIEM (np. "czarnym", "srebrnym")
64
- - "z silnikiem [GAP:2]" uzupełnij NARZĘDNIKIEM (np. "benzynowym", "dieselowym")
65
- - "ma [GAP:3] przebieg" → uzupełnij BIERNIKIEM (np. "mały", "duży")
66
 
67
- PRZYKŁAD:
68
- Input: "Mam [GAP:1] Mercedes w kolorze [GAP:2]."
69
- Output:
70
  {{
71
- "filled_text": "Mam wspaniały Mercedes w kolorze czarnym.",
72
  "gaps": [
73
- {{"index": 1, "marker": "[GAP:1]", "choice": "wspaniały", "alternatives": ["piękny", "zadbany"]}},
74
- {{"index": 2, "marker": "[GAP:2]", "choice": "czarnym", "alternatives": ["srebrnym", "białym"]}}
75
  ]
76
- }}
77
-
78
- WYMAGANY FORMAT ODPOWIEDZI - TYLKO JSON, BEZ KOMENTARZY!"""
79
-
80
- user_content = f"""Uzupełnij luki w poniższym ogłoszeniu samochodowym:
81
-
82
- {text_with_gaps}
83
-
84
- Zwróć TYLKO JSON bez żadnych dodatkowych tekstów. Uzupełnij ALL gaps, w filled_text nie powinno być [GAP:n]!"""
85
 
86
  return [
87
  {"role": "system", "content": system_content},
 
34
  def create_infill_prompt(text_with_gaps: str, options: InfillOptions) -> list[dict]:
35
  """
36
  Creates the chat prompt for gap-filling in car ads.
37
+ Uses function-call format to force structured JSON output.
 
38
 
39
  Args:
40
  text_with_gaps: Ad text with [GAP:n] markers
 
46
  lang_instruction = "po polsku" if options.language == "pl" else "in English"
47
 
48
  system_content = f"""Jesteś ekspertem od uzupełniania tekstów ogłoszeń samochodowych.
49
+ Zawsze odpowiadasz TYLKO prawidłowym JSON-em, bez żadnych innych tekstów."""
50
 
51
+ # More direct instruction with explicit filling examples
52
+ user_content = f"""ZADANIE: Uzupełnij luki w ogłoszeniu samochodowym {lang_instruction}.
 
53
 
54
+ TEKST:
55
+ {text_with_gaps}
 
 
 
56
 
57
+ INSTRUKCJE:
58
+ 1. Zastąp KAŻDY [GAP:n] rzeczywistym słowem/frazą (nie zostawiaj [GAP:n] w tekście!)
59
+ 2. Pamiętaj o polskiej gramatyce (deklinacja)
60
+ 3. Dla każdej luki podaj {options.top_n_per_gap} alternatywne słowa
 
61
 
62
+ ODPOWIEDŹ - TYLKO JSON:
 
 
63
  {{
64
+ "filled_text": "tekst z uzupełnionymi lukami (BEZ [GAP:n])",
65
  "gaps": [
66
+ {{"index": 1, "choice": "słowo1", "alternatives": ["alt1", "alt2"]}}
 
67
  ]
68
+ }}"""
 
 
 
 
 
 
 
 
69
 
70
  return [
71
  {"role": "system", "content": system_content},
app/main.py CHANGED
@@ -422,7 +422,36 @@ async def process_infill_item(
422
  parsed = parse_infill_json(raw_output)
423
 
424
  if not parsed:
425
- # JSON parsing failed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
426
  return InfillResult(
427
  id=item.id,
428
  status="error",
 
422
  parsed = parse_infill_json(raw_output)
423
 
424
  if not parsed:
425
+ # JSON parsing failed - try to extract fills from the raw output
426
+ # Model might have filled the text without JSON wrapper
427
+ print(f"[INFILL] JSON parsing failed, attempting fallback extraction")
428
+ print(f"[INFILL] Raw output: {raw_output[:300]}")
429
+
430
+ # If raw output contains the text with gaps filled (no [GAP:n]),
431
+ # it might be a valid response without JSON
432
+ if "[GAP:" not in raw_output:
433
+ # Model filled the gaps! Extract by comparing with original
434
+ filled_text = raw_output.strip()
435
+
436
+ # Try to build gaps list from what we know
437
+ gap_fills = []
438
+ for i, gap in enumerate(gaps, 1):
439
+ gap_fills.append(GapFill(
440
+ index=i,
441
+ marker=gap.marker,
442
+ choice="(model filled)",
443
+ alternatives=[]
444
+ ))
445
+
446
+ return InfillResult(
447
+ id=item.id,
448
+ status="ok",
449
+ filled_text=filled_text,
450
+ gaps=gap_fills,
451
+ error=None
452
+ )
453
+
454
+ # Otherwise it's a real error
455
  return InfillResult(
456
  id=item.id,
457
  status="error",