Ayona commited on
Commit
240f6e7
·
1 Parent(s): f8e9d1e

refactor prompt assembly for provider-specific caching

Browse files
Files changed (1) hide show
  1. main.py +88 -22
main.py CHANGED
@@ -111,6 +111,71 @@ def _build_openai_reasoning_params(
111
  return params
112
  # ============ End OpenAI Reasoning Helpers ============
113
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  # Initialize embedding model and settings BEFORE importing components
115
  # Priority: OpenAI > Gemini > None
116
  embed_model = None
@@ -815,25 +880,25 @@ def generate_legal_position(
815
  print(f"[DEBUG] FINAL court_decision_text preview: {court_decision_text[:300]}")
816
  print(f"[DEBUG] comment_input: {comment_input[:100] if comment_input else 'Empty'}")
817
 
818
- # Check if placeholders exist in the prompt, if not - append them to the end
819
- if "{court_decision_text}" not in lp_prompt:
820
- print("[WARNING] {court_decision_text} placeholder missing in prompt! Appending to the end.")
821
- lp_prompt += "\n\n<court_decision>\n{court_decision_text}\n</court_decision>"
822
-
823
- if "{comment}" not in lp_prompt:
824
- lp_prompt += "\n\n<comment>\n{comment}\n</comment>"
825
-
826
- content = lp_prompt.format(
827
  court_decision_text=court_decision_text,
828
- comment=comment_input if comment_input else "Коментар відсутній"
829
  )
 
 
 
830
 
831
  # Debug: Check formatted content
832
- print(f"[DEBUG] ===== UNIFIED PROMPT FOR ALL PROVIDERS =====")
833
- print(f"[DEBUG] Formatted content length: {len(content)}")
834
- print(f"[DEBUG] Content preview (first 500 chars): {content[:500]}")
 
 
 
835
  print(f"[DEBUG] Provider: {provider}, Model: {model_name}")
836
- print(f"[DEBUG] ==============================================")
837
 
838
  # Validation check - ensure court_decision_text is not empty
839
  if not court_decision_text or len(court_decision_text.strip()) < 50:
@@ -872,8 +937,8 @@ def generate_legal_position(
872
  role = "developer" if is_reasoning_model else "system"
873
 
874
  messages = [
875
- {"role": role, "content": system_prompt},
876
- {"role": "user", "content": content},
877
  ]
878
 
879
  # Parameters for chat completion
@@ -896,7 +961,7 @@ def generate_legal_position(
896
  )
897
 
898
  # Log full prompts in debug mode
899
- _log_prompt("openai", model_name, system_prompt, content)
900
 
901
  # Execute with retries
902
  for attempt in range(max_retries):
@@ -1054,20 +1119,21 @@ def generate_legal_position(
1054
  client = Anthropic(api_key=ANTHROPIC_API_KEY)
1055
 
1056
  # Debug: check what we're sending to Anthropic
1057
- print(f"[DEBUG] Sending to Anthropic - content length: {len(content)}")
1058
- print(f"[DEBUG] Content preview: {content[:500]}")
 
1059
  print(f"[DEBUG] Anthropic API key configured: {bool(ANTHROPIC_API_KEY)}")
1060
 
1061
  messages = [{
1062
  "role": "user",
1063
- "content": content
1064
  }]
1065
 
1066
  # Prepare message creation parameters
1067
  message_params = {
1068
  "model": model_name,
1069
  "max_tokens": max_tokens or MAX_TOKENS_CONFIG["anthropic"],
1070
- "system": [{"type": "text", "text": system_prompt, "cache_control": {"type": "ephemeral"}}],
1071
  "messages": messages,
1072
  "temperature": temperature
1073
  }
@@ -1106,7 +1172,7 @@ def generate_legal_position(
1106
  message_params["temperature"] = 1.0
1107
 
1108
  # Log full prompts in debug mode
1109
- _log_prompt("anthropic", model_name, system_prompt, content)
1110
 
1111
  # Retry logic for connection errors
1112
  max_retries = 3
 
111
  return params
112
  # ============ End OpenAI Reasoning Helpers ============
113
 
114
+ # ============ Prompt Assembly Helpers ============
115
+ _DYNAMIC_PLACEHOLDERS = ("{court_decision_text}", "{comment}")
116
+ _DEFAULT_COMMENT_TEXT = "Коментар відсутній"
117
+
118
+
119
+ def _ensure_dynamic_placeholders(lp_prompt: str) -> str:
120
+ """Ensure dynamic placeholders exist in the legal-position prompt."""
121
+ updated = lp_prompt
122
+ if "{court_decision_text}" not in updated:
123
+ print("[WARNING] {court_decision_text} placeholder missing in prompt! Appending to the end.")
124
+ updated += "\n\n<court_decision>\n{court_decision_text}\n</court_decision>"
125
+ if "{comment}" not in updated:
126
+ updated += "\n\n<comment>\n{comment}\n</comment>"
127
+ return updated
128
+
129
+
130
+ def _split_legal_position_prompt(lp_prompt: str) -> Tuple[str, str]:
131
+ """Split prompt into static prefix and dynamic suffix starting from first placeholder."""
132
+ positions = [lp_prompt.find(p) for p in _DYNAMIC_PLACEHOLDERS if p in lp_prompt]
133
+ if not positions:
134
+ return lp_prompt.strip(), ""
135
+
136
+ split_at = min(positions)
137
+ static_part = lp_prompt[:split_at].strip()
138
+ dynamic_part = lp_prompt[split_at:].strip()
139
+ return static_part, dynamic_part
140
+
141
+
142
+ def _compile_generation_prompt_blocks(
143
+ system_prompt: str,
144
+ lp_prompt: str,
145
+ court_decision_text: str,
146
+ comment: str,
147
+ ) -> Dict[str, str]:
148
+ """Compile provider-ready prompt blocks without changing UI-facing prompt settings."""
149
+ prepared_lp_prompt = _ensure_dynamic_placeholders(lp_prompt)
150
+ static_lp, dynamic_lp = _split_legal_position_prompt(prepared_lp_prompt)
151
+
152
+ if not dynamic_lp:
153
+ dynamic_lp = "<court_decision>\n{court_decision_text}\n</court_decision>\n\n<comment>\n{comment}\n</comment>"
154
+
155
+ final_comment = comment if comment else _DEFAULT_COMMENT_TEXT
156
+ dynamic_payload = dynamic_lp.format(
157
+ court_decision_text=court_decision_text,
158
+ comment=final_comment,
159
+ )
160
+
161
+ merged_system_prompt = system_prompt.strip()
162
+ if static_lp:
163
+ merged_system_prompt = f"{merged_system_prompt}\n\n{static_lp}" if merged_system_prompt else static_lp
164
+
165
+ full_user_prompt = prepared_lp_prompt.format(
166
+ court_decision_text=court_decision_text,
167
+ comment=final_comment,
168
+ )
169
+
170
+ return {
171
+ "system_prompt": merged_system_prompt,
172
+ "user_prompt": dynamic_payload,
173
+ "full_user_prompt": full_user_prompt,
174
+ "static_prompt": static_lp,
175
+ "dynamic_template": dynamic_lp,
176
+ }
177
+ # ============ End Prompt Assembly Helpers ============
178
+
179
  # Initialize embedding model and settings BEFORE importing components
180
  # Priority: OpenAI > Gemini > None
181
  embed_model = None
 
880
  print(f"[DEBUG] FINAL court_decision_text preview: {court_decision_text[:300]}")
881
  print(f"[DEBUG] comment_input: {comment_input[:100] if comment_input else 'Empty'}")
882
 
883
+ prompt_blocks = _compile_generation_prompt_blocks(
884
+ system_prompt=system_prompt,
885
+ lp_prompt=lp_prompt,
 
 
 
 
 
 
886
  court_decision_text=court_decision_text,
887
+ comment=comment_input,
888
  )
889
+ compiled_system_prompt = prompt_blocks["system_prompt"]
890
+ content = prompt_blocks["full_user_prompt"]
891
+ provider_user_content = prompt_blocks["user_prompt"]
892
 
893
  # Debug: Check formatted content
894
+ print(f"[DEBUG] ===== COMPILED PROMPT BLOCKS =====")
895
+ print(f"[DEBUG] Static system length: {len(compiled_system_prompt)}")
896
+ print(f"[DEBUG] Dynamic user length: {len(provider_user_content)}")
897
+ print(f"[DEBUG] Full content length: {len(content)}")
898
+ print(f"[DEBUG] Static system preview (first 500 chars): {compiled_system_prompt[:500]}")
899
+ print(f"[DEBUG] Dynamic user preview (first 500 chars): {provider_user_content[:500]}")
900
  print(f"[DEBUG] Provider: {provider}, Model: {model_name}")
901
+ print(f"[DEBUG] ==================================")
902
 
903
  # Validation check - ensure court_decision_text is not empty
904
  if not court_decision_text or len(court_decision_text.strip()) < 50:
 
937
  role = "developer" if is_reasoning_model else "system"
938
 
939
  messages = [
940
+ {"role": role, "content": compiled_system_prompt},
941
+ {"role": "user", "content": provider_user_content},
942
  ]
943
 
944
  # Parameters for chat completion
 
961
  )
962
 
963
  # Log full prompts in debug mode
964
+ _log_prompt("openai", model_name, compiled_system_prompt, provider_user_content)
965
 
966
  # Execute with retries
967
  for attempt in range(max_retries):
 
1119
  client = Anthropic(api_key=ANTHROPIC_API_KEY)
1120
 
1121
  # Debug: check what we're sending to Anthropic
1122
+ print(f"[DEBUG] Sending to Anthropic - system length: {len(compiled_system_prompt)}")
1123
+ print(f"[DEBUG] Sending to Anthropic - dynamic user length: {len(provider_user_content)}")
1124
+ print(f"[DEBUG] Anthropic dynamic preview: {provider_user_content[:500]}")
1125
  print(f"[DEBUG] Anthropic API key configured: {bool(ANTHROPIC_API_KEY)}")
1126
 
1127
  messages = [{
1128
  "role": "user",
1129
+ "content": provider_user_content
1130
  }]
1131
 
1132
  # Prepare message creation parameters
1133
  message_params = {
1134
  "model": model_name,
1135
  "max_tokens": max_tokens or MAX_TOKENS_CONFIG["anthropic"],
1136
+ "system": [{"type": "text", "text": compiled_system_prompt, "cache_control": {"type": "ephemeral"}}],
1137
  "messages": messages,
1138
  "temperature": temperature
1139
  }
 
1172
  message_params["temperature"] = 1.0
1173
 
1174
  # Log full prompts in debug mode
1175
+ _log_prompt("anthropic", model_name, compiled_system_prompt, provider_user_content)
1176
 
1177
  # Retry logic for connection errors
1178
  max_retries = 3