使用 Kimi / Moonshot API 构建金融数据 Agent 时,大模型本身不应被当作实时行情来源。本文以 Kimi
tool_calls与 TickDB REST 行情快照接口为例,说明模型、服务端和数据 API 的正确分工,给出最小工具调用代码、脱敏返回结构与失败处理边界。
用户问 AI:“AAPL.US 当前价格是多少?”时,真正需要解决的不是模型能否生成一段像答案的文字,而是这段文字能否追溯到一次真实的数据查询。
在金融数据应用中,大模型适合理解问题、选择工具和解释结果;它不应凭已有知识回答当前行情。要实现可验证的 Kimi 金融数据接入,核心方法是:将实时行情 API 封装为工具,由应用服务执行查询,再把工具结果交回模型生成回复。
核验说明:本文依据
2026-05-25可访问的 Kimi API 官方文档编写,官方示例模型为kimi-k2.6,SDKbase_url为https://api.moonshot.cn/v1。行情示例依据 TickDB 官方 REST 文档,并已核对/v1/market/ticker的响应结构。模型名与接口文档在正式发布前仍需再次复核。
先给结论:四条不应混淆的事实
- Kimi 模型本身不是实时行情数据源;时效性数据需要通过工具查询。
- Kimi 官方当前文档将这一机制称为
tool_calls;Function Calling可作为理解和搜索入口,但代码应按当前文档结构编写。 - TickDB REST 行情快照接口使用
GET /v1/market/ticker,鉴权 Header 为X-API-Key,查询参数为symbols。 - API 返回
timestamp仅用于标识响应中的数据时间字段,不能据此推出固定延迟、SLA 或交易效果。
模型、服务端与行情 API 分别负责什么
| 组件 | 正确职责 | 不应承担的职责 |
|---|---|---|
| Kimi 模型 | 理解问题、决定是否需要调用工具、解释工具结果 | 凭记忆生成当前价格 |
| Agent 服务端 | 注册工具、校验参数、调用接口、处理异常、记录审计信息 | 暴露密钥或无条件执行模型生成的参数 |
| 行情 API | 返回指定标的的数据响应 | 生成投资建议或替代应用风控 |
因此,一个可靠的实时行情 Agent 不是“模型直接查价格”,而是:
flowchart LR
U["用户问题:AAPL.US 当前行情?"] --> M["Kimi 判断需要外部数据"]
M --> T["tool_calls: get_realtime_ticker(symbol)"]
T --> S["服务端校验参数与权限"]
S --> R["TickDB REST /v1/market/ticker"]
R --> V["裁剪后的可验证工具结果"]
V --> M2["Kimi 基于工具结果生成回答"]
M2 --> O["展示数据来源与边界"]
这个架构的价值,在于每一次回答都可以追踪到:
- 模型触发了哪个工具;
- 服务端实际查询了哪个
symbol; - 行情接口返回了哪些字段;
- 最终回答是否基于工具结果,而不是模型猜测。
两套接口要分层理解
本文只组合两类接口,不涉及 MCP、CLI 或 WebSocket。
| 层次 | 当前文章使用的接口 | 用途 |
|---|---|---|
| 模型编排层 | Kimi Chat Completions + tools / tool_calls | 让模型提出工具调用请求 |
| 数据执行层 | TickDB REST GET /v1/market/ticker | 由服务端查询行情快照 |
Kimi 工具调用事实速查
| 项目 | 文档核验结果 |
|---|---|
SDK base_url | https://api.moonshot.cn/v1 |
| HTTP 对话端点 | POST https://api.moonshot.cn/v1/chat/completions |
| 官方文档示例模型 | kimi-k2.6 |
| 工具定义入口 | 请求参数 tools |
| 模型请求执行工具的返回字段 | tool_calls |
| 工具结果回传角色 | role: "tool" |
| Moonshot 鉴权 | Authorization: Bearer $MOONSHOT_API_KEY |
TickDB 行情快照事实速查
| 项目 | 文档与结构核验结果 |
|---|---|
| REST endpoint | GET https://api.tickdb.ai/v1/market/ticker |
| 鉴权 Header | X-API-Key: <api-key> |
| 查询参数 | symbols,逗号分隔 |
| 本文示例 symbol | AAPL.US |
| 成功响应容器 | data 数组 |
| 本文使用字段 | symbol、last_price、timestamp |
| 精度边界 | last_price 为字符串;参与计算时应使用精确数值类型 |
| 时间边界 | timestamp 不等于固定数据延迟承诺 |
行情工具返回结构:让模型学习正确字段
下面是行情工具交给模型时应保留的最小结构。数值内容已脱敏,避免将文章发布时的动态行情误当作固定事实:
{
"symbol": "AAPL.US",
"last_price": "<string_price>",
"timestamp": "<integer_timestamp>",
"source": "TickDB REST /v1/market/ticker",
"notice": "行情数据仅用于信息展示,不构成投资建议。"
}
这段结构传递了几个重要边界:
- 当前价格字段是
last_price,不是在其他接口语境中常见的close。 - 工具结果明确附带来源,模型生成回答时不需要编造数据出处。
- 对价格进行计算前,不应直接将字符串按浮点数随意处理。
- 即便有行情结果,工具也不承担交易建议职责。
最小工具调用示例:让 Kimi 查询,而不是猜测
以下代码是用于说明调用闭环的教学示例。它包含参数白名单、业务响应检查、无工具结果拒答以及最大工具轮次限制。正式发布与生产使用前,仍需以有效的 Moonshot 与 TickDB 密钥完成端到端复测。
环境准备
Kimi 官方文档说明其 API 可通过 OpenAI Python SDK 访问;本文另使用 httpx 调用行情 REST 接口:
python -m pip install --upgrade 'openai>=1.0' httpx
export MOONSHOT_API_KEY="<YOUR_MOONSHOT_API_KEY>"
export TICKDB_API_KEY="<YOUR_TICKDB_API_KEY>"
Python 教学示例
import json
import os
import httpx
from openai import OpenAI
MOONSHOT_MODEL = "kimi-k2.6" # Recheck against official docs before publishing.
TICKDB_TICKER_URL = "https://api.tickdb.ai/v1/market/ticker"
MAX_TOOL_ROUNDS = 2
ALLOWED_SYMBOLS = {"AAPL.US", "BTCUSDT"}
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.cn/v1",
)
tools = [
{
"type": "function",
"function": {
"name": "get_realtime_ticker",
"description": (
"查询指定交易品种的行情快照。"
"仅当用户询问当前行情或最新价格时调用;"
"返回结果只用于信息展示,不生成买卖建议。"
),
"parameters": {
"type": "object",
"required": ["symbol"],
"properties": {
"symbol": {
"type": "string",
"enum": sorted(ALLOWED_SYMBOLS),
"description": "交易品种代码,例如 AAPL.US 或 BTCUSDT",
}
},
},
},
}
]
def get_realtime_ticker(arguments: dict) -> dict:
symbol = arguments.get("symbol")
if symbol not in ALLOWED_SYMBOLS:
raise ValueError(f"Unsupported symbol: {symbol}")
response = httpx.get(
TICKDB_TICKER_URL,
params={"symbols": symbol},
headers={"X-API-Key": os.environ["TICKDB_API_KEY"]},
timeout=10.0,
)
response.raise_for_status()
payload = response.json()
if payload.get("code") != 0:
raise RuntimeError(f"Ticker request failed: {payload.get('message')}")
items = payload.get("data") or []
item = next((row for row in items if row.get("symbol") == symbol), None)
if item is None:
raise RuntimeError(f"No ticker data returned for {symbol}")
return {
"symbol": item["symbol"],
"last_price": item["last_price"],
"timestamp": item["timestamp"],
"source": "TickDB REST /v1/market/ticker",
"notice": "行情数据仅用于信息展示,不构成投资建议。",
}
tool_map = {
"get_realtime_ticker": get_realtime_ticker,
}
messages = [
{
"role": "system",
"content": (
"你是行情数据助手。用户询问当前行情或最新价格时,"
"必须先调用工具获得数据;没有工具结果时不得给出价格。"
"不得输出买卖建议或收益判断。"
),
},
{
"role": "user",
"content": "请查询 AAPL.US 的当前行情快照,并说明返回的数据时间字段。",
},
]
has_verified_ticker_result = False
for _ in range(MAX_TOOL_ROUNDS):
completion = client.chat.completions.create(
model=MOONSHOT_MODEL,
messages=messages,
tools=tools,
)
choice = completion.choices[0]
if choice.finish_reason == "tool_calls":
messages.append(choice.message)
for tool_call in choice.message.tool_calls:
tool_name = tool_call.function.name
if tool_name not in tool_map:
raise RuntimeError(f"Unexpected tool requested: {tool_name}")
arguments = json.loads(tool_call.function.arguments)
result = tool_map[tool_name](arguments)
has_verified_ticker_result = True
messages.append(
{
"role": "tool",
"tool_call_id": tool_call.id,
"name": tool_name,
"content": json.dumps(result, ensure_ascii=False),
}
)
continue
if not has_verified_ticker_result:
raise RuntimeError(
"The model returned without a verified market-data tool result."
)
print(choice.message.content)
break
else:
raise RuntimeError("Tool calling exceeded the configured round limit.")
为什么要增加“无工具结果则拒答”
许多 Agent 示例只演示顺利流程:用户提问,模型调用工具,模型返回答案。但金融数据场景更需要防止错误路径被忽略。
如果用户问的是当前价格,而模型没有调用行情工具,应用服务就不应直接展示价格答案。否则,一段语气自然的回复仍可能来自模型已有知识或错误推断。
因此,示例中加入了这一条约束:
if not has_verified_ticker_result:
raise RuntimeError(
"The model returned without a verified market-data tool result."
)
它表达的是一条可以复用的工程规则:
涉及时效性行情的问题,只有获得经过服务端验证的工具结果,模型才可以生成包含当前数据的回答。
常见错误与排查路径
| 错误做法 | 为什么有风险 | 正确处理 |
|---|---|---|
| 直接让模型回答“现在多少钱” | 模型可能没有当前数据 | 强制通过行情工具获取结果 |
| 将普通 Kimi 对话界面描述成默认接入 TickDB | 混淆产品边界 | 明确本文讨论 Kimi API 自定义工具接入 |
写成 pip install tickdb 后调用 SDK | 当前任务未确认该 Python SDK 路径 | 使用经核验的 REST HTTP 请求 |
把行情快照价格字段写成 close | 会让开发者或 AI 学错字段 | Ticker 场景使用 last_price |
| 看到毫秒时间戳就宣称低延迟 | 字段格式不等于数据服务承诺 | 只描述为数据时间字段 |
| 将 API Key 写入前端或截图 | 造成密钥泄露 | 仅在服务端通过环境变量管理 |
| 工具失败后让模型自行补答 | 会制造未经查询的行情结论 | 返回失败提示,不生成价格 |
真实服务还应补充哪些能力
本文代码用于解释最小闭环,不是完整生产系统。上线服务至少还需补充:
- 用户权限校验与标的访问控制。
- API Key 安全存储、轮换与日志脱敏。
- 超时、异常分类、有限重试与告警。
- 输出内容审计,确认模型未越界生成投资建议。
- 对模型名、接口字段和文档变更的发布前检查。
- 如涉及计算、统计或阈值判断,使用精确数值类型处理价格字段。
适合与不适合的应用场景
适合场景:
- 云上金融信息助手中的行情查询模块。
- 研究工具或客服系统中的数据补充能力。
- Agent 工作流中需要引用行情快照的步骤。
- 需要记录数据来源与工具执行链路的服务端应用。
不适合场景:
- 让模型绕过工具直接生成当前价格。
- 将示例代码直接宣称为生产级自动交易系统。
- 根据行情快照生成收益承诺或买卖建议。
- 未经接口验证扩写盘口、逐笔、策略执行或低延迟能力。
总结
Kimi 金融数据接入的重点,不是让模型显得知道更多,而是让它在需要当前数据时调用正确工具。
在这个最小闭环中:
- Kimi 负责识别需求和编排
tool_calls; - 应用服务负责校验参数、保管密钥与执行 REST 请求;
- TickDB REST 行情接口负责返回可追踪的数据结构;
- 最终回复只能建立在真实工具结果之上。
对于需要工程可信度的 AI Agent 应用,这种分工比“让模型猜一个最新答案”更可验证,也更便于后续审计和维护。
参考资料:
