iT邦幫忙

2025 iThome 鐵人賽

DAY 14
0
AI & Data

雲端情人 - AI 愛系列 第 14

Day14 女朋友功能太多玩壞掉了 :把查股與翻譯「修到會飛」—0050、00937B股市、多國語翻譯直通一次解

  • 分享至 

  • xImage
  •  

好的!我幫你把今天的鐵人賽 Day14 文章生好(主題延續我們這幾天做的 LINE 金融助理:修好查股與翻譯模式)。直接貼到部落格就能用。

系列:打造一個好用又有個性的 LINE 金融助理(股價 / 匯率 / 金價 / 彩票 / 人設 / 翻譯)

🎯 今日目標
1. 修復 查股功能:避開 Yahoo API 401 Unauthorized、台股代碼相容(00937b/00937B 等)。
2. 修復 翻譯模式:開啟後,使用者輸入的每句話都直接翻譯(不中斷、不誤判)。
3. 維持 穩定輸出:OpenAI 金鑰失效時,自動改用 Groq,不影響上線。

🧩 問題現象
• Yahoo 401:直接打 https://query1.finance.yahoo.com/v7/finance/quote 常被擋,導致即時價失敗。
00937b 失敗:台灣 ETF/權證等常見「數字+字母」寫法,yfinance 不認。
• **翻譯模式壞掉:雖然能切換「翻譯->英文」,但之後的訊息會被一般聊天攔走,沒被翻譯。

https://ithelp.ithome.com.tw/upload/images/20250907/20112100zHM6rLEs17.png

🛠️ 解法總覽
1. 改走 HTML 解析:用 YahooStock 直接解析 Yahoo 股市頁面 DOM,拿到名稱/現價/漲跌/時間,避開 401。
2. 代碼正規化:
• 台股大盤/美股大盤:^TWII / ^GSPC。
• 台股:^\d{4,6}[A-Za-z]?$ → 自動補 .TW,英文字尾轉大寫(例:00937b → 00937B.TW)。
• 美股:^[A-Z]{1,5}$ 直接使用(排除 JPY)。
3. 翻譯直通攔截:開啟翻譯模式後,所有訊息都先走翻譯流程;只有結束才回一般聊天。
4. 模型容錯:
• 優先 OpenAI,失敗 → Groq (llama-3.1-8b-instant)。
• 模型名稱改可環境變數覆寫,避免退役爆錯。

🏗️ 關鍵程式片段

  1. 股票代碼正規化(含 00937B)
def normalize_stock_input(user_input: str) -> (str, str):
    s = user_input.strip()
    u = s.upper()

    if u in ["台股大盤", "大盤"]:
        return "^TWII", "台灣加權指數"
    if u in ["美股大盤", "美盤", "美股"]:
        return "^GSPC", "S&P 500 指數"

    if u.endswith(".TW") or u.startswith("^"):
        return u, u
# 台股:4~6位數 + 可選 1 位英文字母(大小寫都行)
    if re.fullmatch(r'\d{4,6}[A-Z]?', u):
        symbol = f"{u}.TW"
        base = re.match(r'(\d{4,6}[A-Z]?)', u).group(1)
        name = get_stock_name(base) or base
        return symbol, name

    if re.fullmatch(r'[A-Z]{1,5}', u) and u not in ["JPY"]:
        return u, u

    return u, s
  1. 翻譯模式「直通」

切換

if low.startswith("翻譯->"):
    lang = msg.split("->", 1)[1].strip()
    if lang == "結束":
        translation_states.pop(chat_id, None)
        return reply_with_quick_bar(reply_token, "✅ 已結束翻譯模式")
    translation_states[chat_id] = lang
    return reply_with_quick_bar(reply_token, f"🌐 已開啟翻譯 → {lang},請直接輸入要翻的內容。")

⭐ 直通攔截(在一般聊天前面)

if chat_id in translation_states:
    out = await translate_text(msg, translation_states[chat_id])
    return reply_with_quick_bar(reply_token, f"🌐 ({translation_states[chat_id]})\n{out}")

3) 即時報價改走 YahooStock

newprice_stock = YahooStock(norm_code)              # 解析 Yahoo HTML
price_data     = stock_price(norm_code)             # 走既有日K函式
news_data      = str(stock_news(display_name))[:1024]
  1. LLM 容錯
def get_analysis_reply(messages):
    try:
        if not openai_client: raise Exception("OpenAI not ready")
        r = openai_client.chat.completions.create(model="gpt-3.5-turbo", messages=messages)
        return r.choices[0].message.content
    except Exception:
        try:
            r = sync_groq_client.chat.completions.create(
                model=os.getenv("GROQ_MODEL_PRIMARY", "llama-3.1-8b-instant"),
                messages=messages, max_tokens=2000, temperature=0.8
            )
            return r.choices[0].message.content
        except Exception:
            r = sync_groq_client.chat.completions.create(
                model=os.getenv("GROQ_MODEL_FALLBACK", "llama-3.1-8b-instant"),
                messages=messages, max_tokens=1500, temperature=1.0
            )
            return r.choices[0].message.content

✅ 驗收清單
• 2330、2002、00937b/00937B 可查,顯示正確名稱/現價/漲跌/時間。
• 台股大盤 / 美股大盤 正確對應 ^TWII / ^GSPC。
• NVDA、QQQ 等美股代碼可查。
• 「翻譯->英文」後,任何文字都直接翻譯;「翻譯->結束」恢復聊天。
• OpenAI 401 時,自動切到 Groq;不中斷服務。

🧪 測試案例
1. 台股 ETF:輸入 00937b → 內部標準化為 00937B.TW → 正常報價。
2. 大盤:輸入 台股大盤 → 指定 ^TWII → 輸出指數報告(不抓營收/配息)。
3. 翻譯:
• 翻譯->英文 → 你好 → Hello
• 翻譯->日文 → 今天下雨嗎? → 今日は雨が降りますか?
• 翻譯->結束 → 回到一般聊天。

🗂️ 今天的提交
• app_fastapi.py:主流程修正(翻譯直通 / 代碼正規化 / 容錯 / 介面維持)。
• YahooStock.py:沿用 HTML 解析方案(避免 Yahoo 401)。

🔭 可能可以加入的功能
• 新增 錯誤回饋卡片(顯示錯誤原因 & 自助檢查步驟)。
• 引入 指令別名(/tw 查台股、/us 查美股…),讓群組裡更好用。
• 加上 快取層:短時間重複查詢直接回覆快取,省時省流量。

** 經測試etf的資訊會少一點

https://ithelp.ithome.com.tw/upload/images/20250907/20112100VfPAyggOdU.png


上一篇
Day 13 她會主動提起(記憶喚醒 & 情境觸發)
下一篇
Day 15讓女助理更有查資訊更「彈性」查詢-黃金、匯率與台股 ETF(含英字尾)的穩定多資料查詢策略
系列文
雲端情人 - AI 愛21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言