|
2 | 2 |
|
3 | 3 | import json |
4 | 4 | import os |
| 5 | +import re |
5 | 6 | from difflib import SequenceMatcher |
6 | 7 | from typing import Any, Dict, List, Optional |
7 | 8 | from urllib.parse import quote |
@@ -238,10 +239,10 @@ def navigation_node(state: GraphState) -> dict: |
238 | 239 | " - If '위치설명' is provided, include that location detail in your answer\n" |
239 | 240 | " - Do not invent location details not in the provided info\n" |
240 | 241 | " - No emoji, no special characters\n" |
241 | | - " - If the persona has a slogan or catchphrase, put it in sign_off, not in answer\n\n" |
| 242 | + f" - If the persona has a slogan or catchphrase, translate it into {lang_name} and put it in sign_off (NOT in Korean).\n\n" |
242 | 243 | f"Place: {place_name} (category: {place.get('category')}){dist_str}{desc_part}\n\n" |
243 | 244 | "Return ONLY valid JSON (no markdown):\n" |
244 | | - '{"answer": "...", "sign_off": "slogan/catchphrase or empty string", "emotion": "GUIDING"}' |
| 245 | + '{"answer": "...", "sign_off": "slogan/catchphrase in target language or empty string", "emotion": "GUIDING"}' |
245 | 246 | ) |
246 | 247 |
|
247 | 248 | messages = build_messages(state, system_msg, text) |
@@ -280,8 +281,8 @@ def navigation_node(state: GraphState) -> dict: |
280 | 281 | error_msg = str(e) |
281 | 282 |
|
282 | 283 | if answer_text: |
283 | | - if sign_off and answer_text.endswith(sign_off): |
284 | | - answer_text = answer_text[:-len(sign_off)].rstrip() |
| 284 | + if sign_off and sign_off in answer_text: |
| 285 | + answer_text = re.sub(r'\s+', ' ', re.sub(r'(?<!\S)' + re.escape(sign_off) + r'(?!\S)', '', answer_text)).strip() |
285 | 286 | if map_url: |
286 | 287 | guide = _MAP_GUIDE.get(user_language, _MAP_GUIDE["en"]) |
287 | 288 | answer_text = f"{answer_text} {guide}" |
@@ -355,10 +356,10 @@ def navigation_node(state: GraphState) -> dict: |
355 | 356 | " - Prioritize same-zone (✓ 같은 구역) places and shorter distances\n" |
356 | 357 | " - Mention the place name and distance\n" |
357 | 358 | " - No emoji, no special characters\n" |
358 | | - " - If the persona has a slogan or catchphrase, put it in sign_off, not in answer\n\n" |
| 359 | + f" - If the persona has a slogan or catchphrase, translate it into {lang_name} and put it in sign_off (NOT in Korean).\n\n" |
359 | 360 | f"Nearby places:\n{places_text}\n\n" |
360 | 361 | "Return ONLY valid JSON (no markdown):\n" |
361 | | - '{"answer": "...", "sign_off": "slogan/catchphrase or empty string", ' |
| 362 | + '{"answer": "...", "sign_off": "slogan/catchphrase in target language or empty string", ' |
362 | 363 | '"place_id": <placeId or null>, "emotion": "GUIDING", "category": "DIRECTION"}' |
363 | 364 | ) |
364 | 365 |
|
@@ -444,8 +445,8 @@ def navigation_node(state: GraphState) -> dict: |
444 | 445 | if error_msg: |
445 | 446 | trace["navigation"]["error"] = error_msg |
446 | 447 |
|
447 | | - if sign_off and answer_text.endswith(sign_off): |
448 | | - answer_text = answer_text[:-len(sign_off)].rstrip() |
| 448 | + if sign_off and sign_off in answer_text: |
| 449 | + answer_text = re.sub(r'\s+', ' ', re.sub(r'(?<!\S)' + re.escape(sign_off) + r'(?!\S)', '', answer_text)).strip() |
449 | 450 | if map_url: |
450 | 451 | guide = _MAP_GUIDE.get(user_language, _MAP_GUIDE["en"]) |
451 | 452 | answer_text = f"{answer_text} {guide}" |
|
0 commit comments