
前言透過這篇文章在先前 簡單聊天機器人 文章中開發的聊天機器人。雖然後續可以新增或調整對話內容但還是固定對話規則型回覆。對應無法匹配的意圖。讓我們結合 LLM 使聊天更靈活自然語氣更像真人 。另外考量效能成本(LLM 只在必要時呼叫)不是所有對話都丟給 LLM。DeepSeek 方案 (需要申請 API Key)相關參看: https://www.deepseek.com/安裝相關模型pip install python-dotenvpython-dotenv 是一個專門用於從 .env 檔案載入環境變數到 Python 程式中的函式庫實作代碼環境變數.envDEEPSEEK_API_KEY你的api_keydeepseek_client.pyimport os import requests from dotenv import load_dotenv load_dotenv() DEEPSEEK_API_KEY os.getenv(DEEPSEEK_API_KEY) def call_deepseek(user_input: str) - str: if not DEEPSEEK_API_KEY: return API key 未設定 url https://api.deepseek.com/chat/completions headers { Authorization: fBearer {DEEPSEEK_API_KEY}, Content-Type: application/json } data { model: deepseek-chat, messages: [{role: user, content: user_input}], max_tokens: 200, # 日常聊天:200-300 tokens temperature: 0.7, # 控制AI輸出的隨機性和創造性,中溫(0.5-0.7) stream: False # 一次性返回完整回复 } try: response requests.post(url, headersheaders, jsondata, timeout30) if response.status_code 200: result response.json() reply result[choices][0][message][content] return reply elif response.status_code 402: return AI 服務額度不足 # 可能要去充值 elif response.status_code 429: return 請求過於頻繁請稍後再試 elif response.status_code 401: return API key 無效 else: print(f[API Error] {response.status_code}: {response.text}) return fAI 錯誤暫時無法使用錯誤代碼:{response.status_code} except requests.exceptions.Timeout: return 請求超時 except requests.exceptions.ConnectionError: return 網路連線失敗請檢查網路 except Exception as e: print(f[ERROR] 請求異常: {e}) return AI 錯誤暫時無法使用註: 參考簡答、摘要: 50-100 tokens普通對話: 200-300 tokenstemperature:0.0 完全確定每次都一樣0.1-0.3 非常穩定稍有變化0.5-0.7 平衡自然對話 聊天機器人0.8-1.0 有創意多樣性simple_chatbot.pyimport os import requests import spacy import json import random from deepseek_client import call_deepseek from dotenv import load_dotenv load_dotenv() DEEPSEEK_API_KEY os.getenv(DEEPSEEK_API_KEY) # 取得 目前 Python 檔案所在的資料夾路徑, 相對路徑 BASE_DIR os.path.dirname(os.path.abspath(__file__)) RESPONSES_PATH os.path.join(BASE_DIR, responses.json) # 載入中文模型 nlp spacy.load(zh_core_web_sm) # 讀取回覆資料 with open(RESPONSES_PATH, r, encodingutf-8) as f: responses json.load(f) def get_response(intent): return random.choice(responses.get(intent, responses[default])) def respond_to_user(user_input): doc nlp(user_input) text user_input.lower() if any(word in text for word in [你好, 哈囉, 嗨, hello, hi]): return get_response(greeting) if any(word in text for word in [你好吗, 你好嗎, 過得]): return get_response(how_are_you) if any(word in text for word in [你是誰, 你的名字]): return get_response(name) if any(word in text for word in [幫助, 能做什麼]): return get_response(help) if any(word in text for word in [笑話, 講個笑話, 逗我笑, 好笑的]): return get_response(jokes) if any(word in text for word in [謝謝, 感謝]): return get_response(thanks) if any(word in text for word in [再見, 掰掰, bye]): return get_response(goodbye) # 使用 NER(人名/地點) for ent in doc.ents: if ent.label_ PERSON: return f你提到了 {ent.text}他是你的朋友嗎 if ent.label_ GPE: return f{ent.text} 聽起來是個地方 # ---------- LLM fallback ---------- return call_deepseek(user_input) if __name__ __main__: print(ChatBot 已啟動輸入「bye」結束對話) while True: user_input input(你) if not user_input.strip(): continue response respond_to_user(user_input) print(ChatBot:, response) if user_input in [bye,再見, 掰掰]: break測試