Files
msh-system/test-doubao-api.py
msh-agent b164d8ba11 feat(ai-chat): 新增豆包API + AI模型配置项支持动态切换
- 后端新增豆包(火山引擎Ark)API集成:DoubaoController、ToolDoubaoServiceImpl,
  使用OkHttp3 SSE流式对话,兼容OpenAI Chat Completions格式
- 新增DoubaoConfig配置类,读取doubao.api.*配置
- 在eb_system_config表新增ai_chat_model配置项,支持doubao/coze/gemini三种模型切换
- 新增GET /api/front/doubao/ai-model-config接口供前端读取当前模型配置
- 前端ai-nutritionist.vue的sendToAI按系统配置分发到_sendViaDoubao/_sendViaCoze/_sendViaGemini
- 前端models-api.js新增doubaoChatStream/doubaoChat/getAiModelConfig函数
- 附带豆包API测试脚本和数据库初始化SQL

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 18:03:21 +08:00

105 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
豆包(火山引擎 ArkAPI 快速测试
用法: python3 test-doubao-api.py
"""
import json, time, sys
try:
import requests
except ImportError:
print("需要安装 requests: pip install requests")
sys.exit(1)
API_KEY = "18480c26-ebcd-4263-8a6f-48359b8bd65d"
BASE_URL = "https://ark.cn-beijing.volces.com/api/v3"
MODEL = "doubao-seed-2-0-pro-260215"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}"
}
print("=" * 50)
print(" 豆包 API 测试")
print("=" * 50)
# ---- 测试 1: 非流式 ----
print("\n【测试 1】非流式调用")
payload = {
"model": MODEL,
"messages": [{"role": "user", "content": "你好,请用一句话介绍你自己"}],
"stream": False
}
start = time.time()
try:
resp = requests.post(f"{BASE_URL}/chat/completions", headers=headers, json=payload, timeout=30)
elapsed = (time.time() - start) * 1000
print(f"HTTP 状态码: {resp.status_code}")
print(f"耗时: {elapsed:.0f} ms")
if resp.status_code == 200:
data = resp.json()
choices = data.get("choices", [])
if choices:
print(f"回复: {choices[0]['message']['content']}")
usage = data.get("usage", {})
print(f"Token: prompt={usage.get('prompt_tokens',0)}, completion={usage.get('completion_tokens',0)}, total={usage.get('total_tokens',0)}")
print(f"模型: {data.get('model', '?')}")
else:
print(f"错误: {resp.text[:500]}")
except Exception as e:
elapsed = (time.time() - start) * 1000
print(f"请求失败 ({elapsed:.0f}ms): {e}")
# ---- 测试 2: 流式 ----
print("\n【测试 2】流式调用 (SSE)")
payload_stream = {
"model": MODEL,
"messages": [{"role": "user", "content": "简单说一下健康饮食的三个要点,每个要点一句话"}],
"stream": True
}
start2 = time.time()
first_token_time = None
full_content = ""
try:
resp2 = requests.post(f"{BASE_URL}/chat/completions", headers=headers, json=payload_stream, stream=True, timeout=30)
print(f"HTTP 状态码: {resp2.status_code}")
if resp2.status_code == 200:
print("流式输出: ", end="", flush=True)
for line in resp2.iter_lines(decode_unicode=True):
if not line:
continue
if line.startswith("data: "):
json_str = line[6:].strip()
if json_str == "[DONE]":
break
try:
evt = json.loads(json_str)
delta = evt.get("choices", [{}])[0].get("delta", {}).get("content", "")
if delta:
if first_token_time is None:
first_token_time = time.time()
full_content += delta
print(delta, end="", flush=True)
except json.JSONDecodeError:
pass
total_time = (time.time() - start2) * 1000
ttft = (first_token_time - start2) * 1000 if first_token_time else 0
print(f"\n---")
print(f"首字时间 (TTFT): {ttft:.0f} ms")
print(f"总耗时: {total_time:.0f} ms")
print(f"回复长度: {len(full_content)} 字符")
else:
print(f"错误: {resp2.text[:500]}")
except Exception as e:
elapsed2 = (time.time() - start2) * 1000
print(f"\n请求失败 ({elapsed2:.0f}ms): {e}")
print("\n" + "=" * 50)
print(" 测试完成")
print("=" * 50)