fix: concise Korean weather reply (current conditions, one sentence)
getWeather returned a verbose multi-section English forecast that the 3B re-synthesised into long, CJK/°F-leaking answers. Hand it a ready-to-speak Korean one-liner (지금 <곳> 날씨는 <상태>, 기온 N도(체감 M도)입니다) and drop the hourly/7-day firehose from the default voice reply.
This commit is contained in:
@@ -175,6 +175,20 @@ WMO_CODES = {
|
|||||||
99: "Thunderstorm with heavy hail",
|
99: "Thunderstorm with heavy hail",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Korean conditions for the concise spoken reply.
|
||||||
|
WMO_CODES_KO = {
|
||||||
|
0: "맑음", 1: "대체로 맑음", 2: "구름 조금", 3: "흐림",
|
||||||
|
45: "안개", 48: "서리 안개",
|
||||||
|
51: "약한 이슬비", 53: "이슬비", 55: "강한 이슬비",
|
||||||
|
56: "약한 어는 이슬비", 57: "강한 어는 이슬비",
|
||||||
|
61: "약한 비", 63: "비", 65: "강한 비",
|
||||||
|
66: "약한 어는 비", 67: "강한 어는 비",
|
||||||
|
71: "약한 눈", 73: "눈", 75: "강한 눈", 77: "싸락눈",
|
||||||
|
80: "약한 소나기", 81: "소나기", 82: "강한 소나기",
|
||||||
|
85: "약한 눈소나기", 86: "강한 눈소나기",
|
||||||
|
95: "천둥번개", 96: "우박 동반 천둥번개", 99: "강한 우박 천둥번개",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class WeatherTool(Tool):
|
class WeatherTool(Tool):
|
||||||
"""Tool for getting current weather using Open-Meteo API."""
|
"""Tool for getting current weather using Open-Meteo API."""
|
||||||
@@ -412,71 +426,31 @@ class WeatherTool(Tool):
|
|||||||
# Get weather description
|
# Get weather description
|
||||||
weather_desc = WMO_CODES.get(weather_code, "Unknown conditions")
|
weather_desc = WMO_CODES.get(weather_code, "Unknown conditions")
|
||||||
|
|
||||||
# Build response text — current conditions
|
# Concise, ready-to-speak Korean one-liner for the voice path. The
|
||||||
lines = [
|
# tool result is normally re-synthesised by the LLM, but a small
|
||||||
f"Current weather in {location_display}:",
|
# model rambles and leaks °F / CJK fragments, so we hand it a clean
|
||||||
f"",
|
# Korean sentence it can echo verbatim (one-sentence system rule).
|
||||||
f"Conditions: {weather_desc}",
|
_ko = WMO_CODES_KO.get(weather_code, weather_desc)
|
||||||
]
|
_short_loc = location_display.split(",")[0].strip() or location_display
|
||||||
|
_ko_parts = [f"지금 {_short_loc} 날씨는 {_ko}"]
|
||||||
if temp_c is not None:
|
if temp_c is not None:
|
||||||
lines.append(f"Temperature: {temp_c}°C ({temp_f}°F)")
|
_t = f"기온 {round(temp_c)}도"
|
||||||
|
if feels_like_c is not None and round(feels_like_c) != round(temp_c):
|
||||||
|
_t += f"(체감 {round(feels_like_c)}도)"
|
||||||
|
_ko_parts.append(_t)
|
||||||
|
ko_sentence = ", ".join(_ko_parts) + "입니다."
|
||||||
|
|
||||||
if feels_like_c is not None and feels_like_c != temp_c:
|
# Build response text — concise current conditions (Korean sentence
|
||||||
lines.append(f"Feels like: {feels_like_c}°C ({feels_like_f}°F)")
|
# first so the model echoes it; English detail kept for any follow-up
|
||||||
|
# reasoning but the forecast firehose is dropped to curb rambling).
|
||||||
if humidity is not None:
|
lines = [
|
||||||
lines.append(f"Humidity: {humidity}%")
|
f"한국어로 정확히 이 한 문장만 답하세요: {ko_sentence}",
|
||||||
|
f"(참고 데이터 — 답변에 추가하지 말 것: {location_display}, {weather_desc}, "
|
||||||
if wind_speed is not None:
|
f"{temp_c}°C feels {feels_like_c}°C, humidity {humidity}%, wind {wind_speed}km/h)",
|
||||||
wind_info = f"Wind: {wind_speed} km/h"
|
]
|
||||||
if wind_gusts and wind_gusts > wind_speed:
|
# Forecast (hourly / 7-day) is intentionally omitted from the default
|
||||||
wind_info += f" (gusts up to {wind_gusts} km/h)"
|
# voice reply to keep it to one spoken sentence; current conditions
|
||||||
lines.append(wind_info)
|
# are what "날씨 알려줘" asks for.
|
||||||
|
|
||||||
# Append today's hourly forecast (remaining hours)
|
|
||||||
hourly = weather_data.get("hourly", {})
|
|
||||||
hourly_times = hourly.get("time", [])
|
|
||||||
hourly_temps = hourly.get("temperature_2m", [])
|
|
||||||
hourly_codes = hourly.get("weather_code", [])
|
|
||||||
|
|
||||||
if hourly_times and hourly_temps:
|
|
||||||
# Get current hour from the current time field
|
|
||||||
current_time = current.get("time", "")
|
|
||||||
current_hour_str = current_time[11:13] if len(current_time) >= 13 else ""
|
|
||||||
current_hour = int(current_hour_str) if current_hour_str.isdigit() else 0
|
|
||||||
today_prefix = current_time[:10] if len(current_time) >= 10 else ""
|
|
||||||
|
|
||||||
hourly_lines = []
|
|
||||||
for i, t in enumerate(hourly_times):
|
|
||||||
if not t.startswith(today_prefix):
|
|
||||||
continue
|
|
||||||
hour_str = t[11:13] if len(t) >= 13 else ""
|
|
||||||
hour = int(hour_str) if hour_str.isdigit() else -1
|
|
||||||
# Show every 3 hours from now onwards
|
|
||||||
if hour > current_hour and hour % 3 == 0 and i < len(hourly_temps) and i < len(hourly_codes):
|
|
||||||
desc = WMO_CODES.get(hourly_codes[i], "")
|
|
||||||
hourly_lines.append(f" {hour:02d}:00 — {hourly_temps[i]}°C, {desc}")
|
|
||||||
|
|
||||||
if hourly_lines:
|
|
||||||
lines.append("")
|
|
||||||
lines.append("Today's forecast (upcoming hours):")
|
|
||||||
lines.extend(hourly_lines)
|
|
||||||
|
|
||||||
# Append daily forecast
|
|
||||||
daily = weather_data.get("daily", {})
|
|
||||||
daily_dates = daily.get("time", [])
|
|
||||||
daily_codes = daily.get("weather_code", [])
|
|
||||||
daily_max = daily.get("temperature_2m_max", [])
|
|
||||||
daily_min = daily.get("temperature_2m_min", [])
|
|
||||||
|
|
||||||
if daily_dates and daily_max and daily_min:
|
|
||||||
lines.append("")
|
|
||||||
lines.append("7-day forecast:")
|
|
||||||
for i, date_str in enumerate(daily_dates):
|
|
||||||
if i < len(daily_max) and i < len(daily_min) and i < len(daily_codes):
|
|
||||||
desc = WMO_CODES.get(daily_codes[i], "")
|
|
||||||
lines.append(f" {date_str}: {daily_min[i]}–{daily_max[i]}°C, {desc}")
|
|
||||||
|
|
||||||
reply_text = "\n".join(lines)
|
reply_text = "\n".join(lines)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user