76 lines
2.8 KiB
Python
76 lines
2.8 KiB
Python
import os
|
||
from dotenv import load_dotenv
|
||
from openai import OpenAI
|
||
from rich.console import Console
|
||
from rich.panel import Panel
|
||
from rich.markdown import Markdown
|
||
from rich.live import Live
|
||
|
||
load_dotenv()
|
||
|
||
# 1. 初始化 Rich 控制台
|
||
console = Console()
|
||
|
||
# 2. 初始化 OpenAI 客戶端 (指向本地 Ollama 或 SiliconFlow)
|
||
client = OpenAI(
|
||
base_url=os.getenv("OLLAMA_BASE_URL"),
|
||
api_key=os.getenv("OLLAMA_API_KEY")
|
||
)
|
||
|
||
# 【核心架構 1】:維護一個對話歷史列表 (這就是 AI 的大腦記憶區)
|
||
# 確保一開始把人設 (System Prompt) 塞進去
|
||
chat_history = [
|
||
{"role": "system", "content": "你是一個精通 Python 的高級工程師,請保持專業且友善的語氣。"}
|
||
]
|
||
|
||
# 印出漂亮的歡迎畫面
|
||
console.print(Panel("✨ 歡迎使用流式 AI 助手!輸入 'quit' 退出。", border_style="green"))
|
||
|
||
# 進入「你問我答」的無限循環
|
||
while True:
|
||
# 替换原来的单行 input()
|
||
console.print("\n👤 [bold green]你 (支持多行输入,输入 '/send' 并回车发送,输入 'quit' 退出):[/bold green]")
|
||
lines = []
|
||
while True:
|
||
line = input()
|
||
if line.strip().lower() == 'quit':
|
||
console.print("[dim]👋 再见![/dim]")
|
||
exit() # 直接退出程序
|
||
if line.strip() == '/send':
|
||
break # 结束输入,跳出收集循环
|
||
lines.append(line)
|
||
|
||
# 将多行列表拼接成一个包含真正换行符的完整字符串
|
||
user_input = "\n".join(lines)
|
||
|
||
# 將使用者的新問題,追加進對話歷史中
|
||
chat_history.append({"role": "user", "content": user_input})
|
||
|
||
# 呼叫大模型,並開啟流式輸出 (stream=True)
|
||
# 注意這裡的 messages 傳入的是完整的 chat_history
|
||
response_stream = client.chat.completions.create(
|
||
model="gemma4:26b", # 替換成你實際運行的模型名稱
|
||
messages=chat_history,
|
||
stream=True
|
||
)
|
||
|
||
full_response = ""
|
||
|
||
# 【核心架構 3】:使用 Live 區塊進行 UI 即時渲染
|
||
with Live(Panel("思考中...", title="🤖 AI", border_style="cyan"), refresh_per_second=15) as live:
|
||
for chunk in response_stream:
|
||
content = chunk.choices[0].delta.content
|
||
if content is not None:
|
||
full_response += content
|
||
# 即時更新青色的對話框
|
||
live.update(
|
||
Panel(
|
||
Markdown(full_response),
|
||
title="🤖 AI",
|
||
border_style="cyan"
|
||
)
|
||
)
|
||
|
||
# 【核心架構 4】:將 AI 剛剛吐出來的完整回答,存回對話歷史中
|
||
# 這樣下一輪對話時,AI 才會「記得」它自己剛剛說過什麼
|
||
chat_history.append({"role": "assistant", "content": full_response}) |