codeBOKER Copilot commited on
Commit
d4cfc10
ยท
1 Parent(s): 87c0663

Fix Arabic brand spelling by normalizing incorrect variants in AI replies and strengthen system prompt guidance

Browse files
app/ai/orchestrator.py CHANGED
@@ -1,5 +1,6 @@
1
  import json
2
  import logging
 
3
  from typing import Any
4
 
5
  from app.ai.providers import (
@@ -120,7 +121,7 @@ class AIOrchestrator:
120
  temperature=temperature,
121
  )
122
  if not response.tool_calls:
123
- content = (response.content or "").strip()
124
  if content:
125
  return content
126
  raise RetryableProviderError(f"{provider.name} returned an empty response")
@@ -163,6 +164,26 @@ def _assistant_tool_message(response: AIProviderResponse) -> dict[str, Any]:
163
  }
164
 
165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  async def _execute_tool_call(registry: ToolRegistry, tool_call: ToolCall) -> ToolResult:
167
  try:
168
  arguments = json.loads(tool_call.arguments or "{}")
 
1
  import json
2
  import logging
3
+ import re
4
  from typing import Any
5
 
6
  from app.ai.providers import (
 
121
  temperature=temperature,
122
  )
123
  if not response.tool_calls:
124
+ content = _normalize_brand_name((response.content or "").strip())
125
  if content:
126
  return content
127
  raise RetryableProviderError(f"{provider.name} returned an empty response")
 
164
  }
165
 
166
 
167
+ def _normalize_brand_name(text: str) -> str:
168
+ if not text:
169
+ return text
170
+
171
+ replacements = {
172
+ "ูู„ุณุง": "ูู„ุฒุฉ",
173
+ "ูู„ุธ": "ูู„ุฒุฉ",
174
+ "ูู„ุธุฉ": "ูู„ุฒุฉ",
175
+ "ูู„ุฒ": "ูู„ุฒุฉ",
176
+ "ูู„ูุฒุฉ": "ูู„ุฒุฉ",
177
+ "ูู„ูŽุฒุฉ": "ูู„ุฒุฉ",
178
+ "ูู„ูฐุฒุฉ": "ูู„ุฒุฉ",
179
+ }
180
+
181
+ for wrong, correct in sorted(replacements.items(), key=lambda item: -len(item[0])):
182
+ pattern = rf"(?<![\w\u0600-\u06FF]){re.escape(wrong)}(?![\w\u0600-\u06FF])"
183
+ text = re.sub(pattern, correct, text)
184
+ return text
185
+
186
+
187
  async def _execute_tool_call(registry: ToolRegistry, tool_call: ToolCall) -> ToolResult:
188
  try:
189
  arguments = json.loads(tool_call.arguments or "{}")
prompts/system.md CHANGED
@@ -1,7 +1,8 @@
1
- You are FALZH, a WhatsApp travel booking assistant.
2
 
3
  Rules:
4
  - Reply in sender's language (Arabic/English). Be concise, warm, practical.
 
5
  - For new users: be extra warm and welcoming. Greet them, introduce FALZH briefly, and guide them to their first action.
6
  - Use `about_falzh` for company/FAQ/policy/pricing/support.
7
  - Tool args: Arabic for departure/destination/vehicle_type/time labels. English for digits/times.
 
1
+ You are FALZH | ูู„ุฒุฉ, a WhatsApp travel booking assistant.
2
 
3
  Rules:
4
  - Reply in sender's language (Arabic/English). Be concise, warm, practical.
5
+ - When writing in Arabic, the brand name must always be spelled exactly "ูู„ุฒุฉ" (ู-ู„-ุฒ-ุง). Never use "ูู„ุณุง", "ูู„ุธ", "ูู„ุธุฉ", "ูู„ุฒ", or any other variant.
6
  - For new users: be extra warm and welcoming. Greet them, introduce FALZH briefly, and guide them to their first action.
7
  - Use `about_falzh` for company/FAQ/policy/pricing/support.
8
  - Tool args: Arabic for departure/destination/vehicle_type/time labels. English for digits/times.
prompts/system_new_user.md CHANGED
@@ -8,4 +8,4 @@ It is the sender's first message. Welcome them warmly and introduce FALZH with a
8
  4. Use emojis (๐Ÿš—, ๐Ÿšš, etc.) and friendly tone. Be warm, not robotic.
9
  5. Keep it short โ€” 4-5 lines max. Do not over-explain.
10
  6. Never ask for name of a passenger. Only ask for name if they want to become a driver.
11
- 7. The brand name is ALWAYS "ูู„ุฒุฉ" (ู-ู„-ุฒ-ุง) โ€” never "ูู„ุณุง" or any other variant.
 
8
  4. Use emojis (๐Ÿš—, ๐Ÿšš, etc.) and friendly tone. Be warm, not robotic.
9
  5. Keep it short โ€” 4-5 lines max. Do not over-explain.
10
  6. Never ask for name of a passenger. Only ask for name if they want to become a driver.
11
+ 7. The brand name is ALWAYS "ูู„ุฒุฉ" (ู-ู„-ุฒ-ุง) โ€” never "ูู„ุณุง", "ูู„ุธ", "ูู„ุธุฉ", "ูู„ุฒ", or any other variant.
tests/test_ai_orchestrator.py CHANGED
@@ -109,6 +109,24 @@ async def test_ai_executes_tool_call_and_returns_final_response():
109
  assert '"ok": true' in second_call_messages[-1]["content"]
110
 
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  @pytest.mark.asyncio
113
  async def test_ai_reports_invalid_tool_arguments_to_model():
114
  primary = ScriptedProvider(
 
109
  assert '"ok": true' in second_call_messages[-1]["content"]
110
 
111
 
112
+ @pytest.mark.asyncio
113
+ async def test_ai_normalizes_incorrect_arabic_brand_spelling():
114
+ primary = ScriptedProvider(
115
+ "groq",
116
+ [AIProviderResponse(content="ุฃู‡ู„ุงู‹ ุจูƒ ููŠ ูู„ุธ! ุฃุชู…ู†ู‰ ุฃุญุฌุฒ ู„ูƒ ุฑุญู„ุฉ.")],
117
+ )
118
+ orchestrator = AIOrchestrator(
119
+ primary=primary,
120
+ fallback=ScriptedProvider("openrouter", []),
121
+ temperature=0.2,
122
+ max_tool_iterations=3,
123
+ )
124
+
125
+ reply = await orchestrator.generate_reply(messages=[], tools=[], registry=ToolRegistry())
126
+
127
+ assert reply == "ุฃู‡ู„ุงู‹ ุจูƒ ููŠ ูู„ุฒุฉ! ุฃุชู…ู†ู‰ ุฃุญุฌุฒ ู„ูƒ ุฑุญู„ุฉ."
128
+
129
+
130
  @pytest.mark.asyncio
131
  async def test_ai_reports_invalid_tool_arguments_to_model():
132
  primary = ScriptedProvider(