Spaces:
Sleeping
Sleeping
Ayona commited on
Commit ·
240f6e7
1
Parent(s): f8e9d1e
refactor prompt assembly for provider-specific caching
Browse files
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 |
-
|
| 819 |
-
|
| 820 |
-
|
| 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
|
| 829 |
)
|
|
|
|
|
|
|
|
|
|
| 830 |
|
| 831 |
# Debug: Check formatted content
|
| 832 |
-
print(f"[DEBUG] =====
|
| 833 |
-
print(f"[DEBUG]
|
| 834 |
-
print(f"[DEBUG]
|
|
|
|
|
|
|
|
|
|
| 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":
|
| 876 |
-
{"role": "user", "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,
|
| 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 -
|
| 1058 |
-
print(f"[DEBUG]
|
|
|
|
| 1059 |
print(f"[DEBUG] Anthropic API key configured: {bool(ANTHROPIC_API_KEY)}")
|
| 1060 |
|
| 1061 |
messages = [{
|
| 1062 |
"role": "user",
|
| 1063 |
-
"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":
|
| 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,
|
| 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
|