Initial commit with Llama API client and docs
Add Python scripts for Llama API chat clients, endpoint testing, and quick tests. Include documentation (README, CONTRIBUTING, 操作指南), license, and .gitignore. Supports multiple endpoints and models for OpenAI-compatible Llama API usage.
This commit is contained in:
196
llama_chat.py
Normal file
196
llama_chat.py
Normal file
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Llama 內網 API 對話程式
|
||||
支援多個端點和模型選擇
|
||||
"""
|
||||
|
||||
from openai import OpenAI
|
||||
import sys
|
||||
import re
|
||||
|
||||
# API 配置
|
||||
API_KEY = "paVrIT+XU1NhwCAOb0X4aYi75QKogK5YNMGvQF1dCyo="
|
||||
|
||||
# 可用端點 (前 3 個已測試可用)
|
||||
ENDPOINTS = [
|
||||
"http://192.168.0.6:21180/v1",
|
||||
"http://192.168.0.6:21181/v1",
|
||||
"http://192.168.0.6:21182/v1",
|
||||
"http://192.168.0.6:21183/v1"
|
||||
]
|
||||
|
||||
# 模型列表
|
||||
MODELS = [
|
||||
"gpt-oss-120b",
|
||||
"deepseek-r1-671b",
|
||||
"qwen3-embedding-8b"
|
||||
]
|
||||
|
||||
def clean_response(text):
|
||||
"""清理 AI 回應中的特殊標記"""
|
||||
# 移除思考標記
|
||||
if "<think>" in text:
|
||||
text = re.sub(r'<think>.*?</think>', '', text, flags=re.DOTALL)
|
||||
|
||||
# 移除 channel 標記
|
||||
if "<|channel|>" in text:
|
||||
parts = text.split("<|message|>")
|
||||
if len(parts) > 1:
|
||||
text = parts[-1]
|
||||
|
||||
# 移除結束標記
|
||||
text = text.replace("<|end|>", "").replace("<|start|>", "")
|
||||
|
||||
# 清理多餘空白
|
||||
text = text.strip()
|
||||
|
||||
return text
|
||||
|
||||
def test_endpoint(endpoint):
|
||||
"""測試端點是否可用"""
|
||||
try:
|
||||
client = OpenAI(api_key=API_KEY, base_url=endpoint)
|
||||
response = client.chat.completions.create(
|
||||
model="gpt-oss-120b",
|
||||
messages=[{"role": "user", "content": "Hi"}],
|
||||
max_tokens=10,
|
||||
timeout=5
|
||||
)
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def chat_session(endpoint, model):
|
||||
"""對話主程式"""
|
||||
print("\n" + "="*60)
|
||||
print("Llama AI 對話系統")
|
||||
print("="*60)
|
||||
print(f"端點: {endpoint}")
|
||||
print(f"模型: {model}")
|
||||
print("\n指令:")
|
||||
print(" exit/quit - 結束對話")
|
||||
print(" clear - 清空對話歷史")
|
||||
print(" model - 切換模型")
|
||||
print("-"*60)
|
||||
|
||||
client = OpenAI(api_key=API_KEY, base_url=endpoint)
|
||||
messages = []
|
||||
|
||||
while True:
|
||||
try:
|
||||
user_input = input("\n你: ").strip()
|
||||
|
||||
if not user_input:
|
||||
continue
|
||||
|
||||
if user_input.lower() in ['exit', 'quit']:
|
||||
print("再見!")
|
||||
break
|
||||
|
||||
if user_input.lower() == 'clear':
|
||||
messages = []
|
||||
print("[系統] 對話歷史已清空")
|
||||
continue
|
||||
|
||||
if user_input.lower() == 'model':
|
||||
print("\n可用模型:")
|
||||
for i, m in enumerate(MODELS, 1):
|
||||
print(f" {i}. {m}")
|
||||
choice = input("選擇 (1-3): ").strip()
|
||||
if choice in ['1', '2', '3']:
|
||||
model = MODELS[int(choice)-1]
|
||||
print(f"[系統] 已切換到 {model}")
|
||||
continue
|
||||
|
||||
messages.append({"role": "user", "content": user_input})
|
||||
|
||||
print("\nAI 思考中...", end="", flush=True)
|
||||
|
||||
try:
|
||||
response = client.chat.completions.create(
|
||||
model=model,
|
||||
messages=messages,
|
||||
temperature=0.7,
|
||||
max_tokens=1000
|
||||
)
|
||||
|
||||
ai_response = response.choices[0].message.content
|
||||
ai_response = clean_response(ai_response)
|
||||
|
||||
print("\r" + " "*20 + "\r", end="") # 清除 "思考中..."
|
||||
print(f"AI: {ai_response}")
|
||||
|
||||
messages.append({"role": "assistant", "content": ai_response})
|
||||
|
||||
except UnicodeEncodeError:
|
||||
print("\r[錯誤] 編碼問題,請使用英文對話")
|
||||
messages.pop() # 移除最後的用戶訊息
|
||||
except Exception as e:
|
||||
print(f"\r[錯誤] {str(e)[:100]}")
|
||||
messages.pop() # 移除最後的用戶訊息
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n[中斷] 使用 exit 命令正常退出")
|
||||
continue
|
||||
except EOFError:
|
||||
print("\n再見!")
|
||||
break
|
||||
|
||||
def main():
|
||||
print("="*60)
|
||||
print("Llama 內網 API 對話程式")
|
||||
print("="*60)
|
||||
|
||||
# 測試端點
|
||||
print("\n正在檢查可用端點...")
|
||||
available = []
|
||||
for i, endpoint in enumerate(ENDPOINTS[:3], 1): # 只測試前3個
|
||||
print(f" 測試 {endpoint}...", end="", flush=True)
|
||||
if test_endpoint(endpoint):
|
||||
print(" [OK]")
|
||||
available.append(endpoint)
|
||||
else:
|
||||
print(" [失敗]")
|
||||
|
||||
if not available:
|
||||
print("\n[錯誤] 沒有可用的端點")
|
||||
sys.exit(1)
|
||||
|
||||
# 選擇端點
|
||||
if len(available) == 1:
|
||||
selected_endpoint = available[0]
|
||||
print(f"\n使用端點: {selected_endpoint}")
|
||||
else:
|
||||
print(f"\n找到 {len(available)} 個可用端點:")
|
||||
for i, ep in enumerate(available, 1):
|
||||
print(f" {i}. {ep}")
|
||||
print("\n選擇端點 (預設: 1): ", end="")
|
||||
choice = input().strip()
|
||||
if choice and choice.isdigit() and 1 <= int(choice) <= len(available):
|
||||
selected_endpoint = available[int(choice)-1]
|
||||
else:
|
||||
selected_endpoint = available[0]
|
||||
|
||||
# 選擇模型
|
||||
print("\n可用模型:")
|
||||
for i, model in enumerate(MODELS, 1):
|
||||
print(f" {i}. {model}")
|
||||
print("\n選擇模型 (預設: 1): ", end="")
|
||||
choice = input().strip()
|
||||
if choice in ['1', '2', '3']:
|
||||
selected_model = MODELS[int(choice)-1]
|
||||
else:
|
||||
selected_model = MODELS[0]
|
||||
|
||||
# 開始對話
|
||||
chat_session(selected_endpoint, selected_model)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n程式已退出")
|
||||
except Exception as e:
|
||||
print(f"\n[錯誤] {e}")
|
||||
sys.exit(1)
|
Reference in New Issue
Block a user