先聊一个挺现实的感受:很多团队拿DeepSeek和Kimi的API Key,第一个请求十分钟就调通了,但半年之后系统还是进不了生产环境。原因不是不会调用接口,而是从“能把模型跑起来”到“企业级AI系统构建”之间,隔着一整条链路——选型、超时、重试、限流、Token成本、结构化输出、兜底策略,这些在官方文档里不会集中写清楚的事,才是真正的实战。
这篇就把这条链路完整梳理一遍。我不打算只贴代码,也不会只讲概念,而是按照一个真实项目从零到上线的节奏,把DeepSeek与Kimi API应用从入门到精通需要的所有关键环节拆开讲。内容会有点长,建议先收藏。适合有Python基础、正在公司内部做AI应用落地,或者准备把大模型能力接入业务系统的开发者和架构师。
1. 两个模型,一冷一热的定位:先回答“为什么是它们”
1.1 DeepSeek更擅长什么,Kimi更擅长什么
很多人选模型时习惯看跑分榜单,谁分数高就用谁。但在企业环境里,跑分只能作为参考,真正要看的还是业务场景的匹配度。
我对这两个模型的实际体验差异很明显。DeepSeek在代码生成、逻辑推理、数学计算这类“硬核思考”任务上表现非常稳,把它用在数据分析、报表解读、开发辅助、复杂规则判断这些场景,输出质量明显更好。尤其是需要多步推理的问题,它的回答结构更完整,不太容易出现“步骤跳变”或者“结论自相矛盾”的情况。
Kimi给我最深的印象则是超长文本的处理能力。我们当时有大量几十页的产品说明书、历史客服话术、政策服务文档,一般模型塞不进去,或者塞进去之后“记不住”前面的内容。Kimi在这类长文档解读、信息抽取、知识库问答场景里几乎是量身定做的。它的中文表达也更自然,回答客服类问题的时候,语气不那么“机械”。
这两种能力实际上是互补的。企业里的大部分AI应用,要么面对的是复杂的逻辑问题,要么面对的是海量的文本资料,甚至会同时遇到。所以我的观点一直很明确:不要纠结“哪个模型更强”,要问“哪条API链路更适合我的业务”。
1.2 企业选型的判断逻辑
我把选型标准总结成四个维度:任务类型、输入长度、响应速度、成本预算。
如果任务是“读完一份很长的合同,找出风险条款”,那优先考虑长文本优势明显的Kimi。如果任务是“根据用户的提问,生成一段SQL查询”,DeepSeek的推理能力往往更靠谱。如果任务对响应延迟敏感,比如用户正在等客服回复,要优先测试两个模型的首Token延迟和稳定性。如果任务是高频、大量调用,比如每天几十万次的内容分类,那么性价比就是第一要素。
我建议把任务试跑一遍再决定,不要看参数猜。选型阶段多花一天,后面上线能省一个月。
1.3 双模型路由:我为什么不再只押注一个
之前在某电商平台做一个智能问答模块时,我们一开始只接了单个模型,结果遇到两个问题:一是长文档场景表现一般,二是所有请求挤在一个模型上,偶尔接口波动,整体服务就会跟着抖动。
后来我们把模型层改成了双通路——按请求特征做路由:需要复杂推理的走DeepSeek,需要处理长文本上下文或需要更自然中文表达的走Kimi。成本最直观的变化是总Token消耗下降了一块,因为每个请求都能选更合适的模型,不会出现“用大模型干小活”的浪费。
这个结构也带来一个额外好处:当一个模型服务不稳定时,可以直接把流量切到另一个,业务不用硬扛。后面第4章我会详细讲怎么把这种切换变成自动化机制。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与第一行可用代码:把API Key变成一次真实对话
2.1 密钥申请与权限隔离
DeepSeek和Kimi都有对应的开放平台,注册账号之后在控制台创建API Key即可。注意一点:API Key等同于账号密码,千万不要写进前端代码、Git仓库或者能被同事随便看到的配置文件里。
企业环境里我的习惯是统一走后端。服务端从配置中心或环境变量读取密钥,前端只跟自己的后端交互,由后端再转发给大模型API。这样密钥只有一个出口,泄露面大大缩小。即使要做内部测试,也建议用独立的测试Key,跟生产Key分开,方便出问题时快速定位和吊销。
2.2 用Python完成第一次对话补全
两个平台都提供了兼容OpenAI格式的接口,所以我们可以用同一套Python SDK来调用。先安装依赖:
bash复制pip install openai python-dotenv
建立项目目录,在.env文件里写配置,同时把它加进.gitignore:
bash复制LLM_API_KEY=sk-你的密钥
LLM_BASE_URL=https://官方提供的BaseURL
LLM_MODEL=模型名称以官方文档为准
然后写一个最简单的补全请求:
python复制import os
from openai import OpenAI
client = OpenAI(
api_key=os.getenv("LLM_API_KEY"),
base_url=os.getenv("LLM_BASE_URL"),
timeout=30.0
)
def chat_once(user_content):
resp = client.chat.completions.create(
model=os.getenv("LLM_MODEL"),
messages=[
{"role": "system", "content": "你是一个严谨的助手。"},
{"role": "user", "content": user_content}
]
)
return resp.choices[0].message.content
if __name__ == "__main__":
print(chat_once("请用一句话解释什么是API"))
这里有三点值得解释。第一,model参数必须以官方文档为准,不同入口模型名会更新,硬编码在代码里很容易跟着过期。第二,messages数组里至少要有user角色,system角色可以用来约束模型的行为方式。第三,timeout参数一开始就要设置,不然后台如果出现网络波动,请求会长时间挂起,拖垮整个业务流程。
2.3 别急着调参:先搞懂temperature和max_tokens
第一次跑通之后,很多人会急着调各种参数,其实真正需要关心的核心参数就两个。
temperature控制随机性,取值范围一般是0到1以上。偏向稳定输出的任务,比如信息抽取、内容分类,设成0到0.3比较合适。偏向创意写作、脑暴文案的,可以调到0.7以上。注意:不是所有平台都完全按同一尺度定义该参数,整体语感是“越小越稳、越大越散”。
max_tokens限制的是输出长度,它不限制输入。有些同学误以为设了max_tokens就能同时卡住输入和输出,导致成本失控。在DeepSeek和Kimi的计费逻辑里,输入和输出是分开计费的,max_tokens只决定这一次回答最多能输出多少Token,输入长度要靠消息体本身控制。
初期建议先不要动top_p、presence_penalty、frequency_penalty这些参数,保持平台默认值跑一两个星期,等业务稳定了再根据线上日志微调。调参最忌讳拍脑袋,每一步调整都应该有数据支撑。
3. 从Demo到产品级体验:流式输出、函数调用、结构化JSON
3.1 流式输出:让用户看到模型“打字”
如果用户向AI提问之后要一直干等几秒甚至十几秒,体验会很差。非流式模式是等模型生成完整个回答才返回,流式模式则是一边生成一边返回,前端拿到数据后可以像打字机一样逐字展示。
开启流式的方式很简单:
python复制resp = client.chat.completions.create(
model=os.getenv("LLM_MODEL"),
messages=messages,
stream=True
)
for chunk in resp:
delta = chunk.choices[0].delta.content
if delta:
yield delta
这里有个企业落地细节:后端要把流式响应转成SSE格式再推给前端,不要在本地攒完整个句子再一次性发给浏览器,那等于没开流式。SSE的规范很简单,每个数据块以“data:”开头,以换行分隔。即时反馈带来的体验提升,远比想象中明显。
流式模式有一个代价:复制了超时、中断、重连等问题,需要额外的断点处理。所以我的建议是:面向真实用户互动的场景,优先上流式;离线批处理场景,比如夜里批量生成摘要,用非流式更省事。
3.2 函数调用:让模型从“聊天”变成“办事”
这是从入门到精通的分水岭。只靠Prompt里的提示词,模型最多是“一个会说话的机器人”,但接入了函数调用之后,模型就能真正驱动业务系统完成操作。
举个例子:客服机器人需要查询订单状态。正常情况下,模型并不知道订单系统的数据,我们也不能让它瞎编。正确的做法是给模型声明一个“查询订单”的工具,模型在合适的时机返回一个工具调用请求,由我们自己的代码去数据库查询,再把真实结果传回给模型生成最终回答。
python复制tools = [
{
"type": "function",
"function": {
"name": "query_order_status",
"description": "根据订单号查询订单当前状态",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "客户提供的订单号"}
},
"required": ["order_id"]
}
}
}
]
resp = client.chat.completions.create(
model=os.getenv("LLM_MODEL"),
messages=[
{"role": "system", "content": "你是电商客服助手,回答必须基于工具返回的真实数据,不要编造。"},
{"role": "user", "content": "帮我看看订单A12345到哪了"}
],
tools=tools,
tool_choice="auto"
)
msg = resp.choices[0].message
if msg.tool_calls:
for call in msg.tool_calls:
print("模型想调用:", call.function.name)
print("参数是:", call.function.arguments)
拿到模型返回的tool_calls之后,我们自己执行对应函数,把结果以role=tool的消息追加回messages,再次调用模型,模型就会基于真实数据组织回复。这里的关键是千万不要把工具结果交给模型去“凭空生成”,工具结果必须真实,否则就失去了接入业务系统的意义。
DeepSeek和Kimi目前都支持类似的Tool Calling能力,声明格式基本兼容,但细节字段要以各平台文档为准。函数调用能力强不强,直接决定了AI系统能对接多少内部业务。凡是涉及查库、下单、计算、调第三方系统的,都应该走工具调用,而不是靠模型背诵。
3.3 结构化输出:告别花式JSON解析
很多团队在让模型返回JSON时,用的是“请在JSON里返回”这句话。结果模型偶尔会在JSON外面多出一句“好的,以下是答案”,导致json.loads直接报错。
更稳的做法是三层保险。
第一层,在System Prompt里明确输出格式,并严格约束“不要输出任何额外说明”。第二层,如果平台支持json_object之类的结构化输出参数,直接开启。第三层,把返回结果放进前面讲的函数调用流程里,让模型通过tool_calls携带结构化参数,这样拿到的就是干净的JSON字符串。
我在实际项目里最常用的做法是第三层。因为函数调用的parameters本身就是JSON Schema,模型必须按照Schema输出参数,规避了格式漂移。解析逻辑也变得非常统一:获取call.function.arguments,然后json.loads,失败再走重试。
3.4 什么时候该用哪一套组合
简单闲聊、内容生成这类场景,不需要结构化输出,也不用接函数调用,流式输出就够了。需要固定信息提取、表单填写的,用“System Prompt + 结构化输出参数”。需要触达业务系统的,必须用函数调用,把动作真正落到代码层。
组合没有绝对的对错,但有一条底线:任何要进数据库或者要扣用户资产的操作,都必须在工具函数里做权限校验和二次确认。大模型可以当“调度员”,但“执行者”必须是经过审核的内部代码。
4. 大模型API的可靠性工程:超时、重试、限流与兜底
4.1 把超时当成功能而不是异常
外部API不稳定是常态,大模型接口尤其如此。网络闪断、服务端排队、限流触发,都会导致请求迟迟不返回。如果代码里没设超时,用户请求会一直挂在线程池里,线程耗尽之后整个服务跟着雪崩。
我的做法是区分连接超时和读超时。连接超时可以短一点,比如5到10秒,它只负责建立连接。读超时要根据模型生成时间合理设置,长文本生成可能确实需要几十秒,读超时设太短会导致明明在正常生成却被强行打断。
python复制client = OpenAI(
api_key=os.getenv("LLM_API_KEY"),
base_url=os.getenv("LLM_BASE_URL"),
timeout=(10.0, 60.0)
)
然后要习惯在一开始就把超时时间做成可配置项,不要写死在代码里。线上出问题时,第一时间调整配置比重新发版快得多。
4.2 重试策略设计:既要恢复又要防重
遇到可恢复的异常,比如5xx、429、超时,通常需要重试。但重试不是无脑循环。我用的方案是“指数退避加抖动”:第一次失败等1秒,第二次等2秒,第三次等4秒,最多重试3到5次,同时每次在基础上加一个随机偏移,避免大量请求同时重试造成“重试风暴”。
这里有一个容易被忽略的问题:模型生成本身是非幂等的。第一次调用可能已经生成了一半回答,但因为网络问题你的服务端没收到完整结果,重试时模型会从头生成一遍。对于普通问答场景这没问题,但如果这个API调用后面连接了扣款、发券、通知等操作,重试就可能导致重复执行。
所以原则是:重试只发生在“模型调用”这一层,业务操作要放在调用成功并校验完之后再执行,或者给业务操作本身设计幂等键。不要让重试机制跨过业务边界去重放整个业务流程。
4.3 限流与并发治理
开放平台通常会有每分钟请求数和Token消耗量的限制。触发429时,服务方会返回限流信号,这时候再继续硬冲反而会拉长惩罚时间。
企业内部的治理思路有两个方向。一个是“入口控制”:在请求进入模型调用层之前,用信号量或令牌桶限制最大并发,超出的请求排队等待。另一个是“削峰填谷”:把非实时任务放到消息队列里异步消化,而不是高峰时直接打到模型API。
python复制import threading
import time
class RateLimiter:
def __init__(self, max_calls_per_minute):
self.interval = 60.0 / max_calls_per_minute
self.lock = threading.Lock()
self.next_time = time.time()
def wait(self):
with self.lock:
now = time.time()
if now < self.next_time:
time.sleep(self.next_time - now)
self.next_time = max(self.next_time, now) + self.interval
这段代码只是一个最简实现,生产环境可以换成更成熟限流组件。重点是思路:把并发控制在平台允许范围内,而不是依赖平台429之后被动退避。
4.4 兜底预案是最后的体面
不管前面做了多少优化,模型API总会有彻底不可用的时候。企业级系统必须具备“绕着走”的能力。
我把兜底分成三级。第一级是降级文案,当模型调用失败时,接口返回预设的友好提示,而不是抛出异常让用户看到一片空白。第二级是静态答案兜底,对于一些高频固定问题,直接从缓存里取答案,根本不依赖大模型。第三级是切换备用模型,把DeepSeek的流量切到Kimi,或者反过来,至少保证业务有响应。
三级兜底的优先级应该写清楚:先尝试切换模型,再查语义缓存,最后才走静态文案。切换模型的逻辑要前置预检,比如连续失败N次就自动拉起熔断,而不是每个请求都再试一次。
5. 成本治理:Token预算、语义缓存与模型降级
5.1 算清楚每一笔Token开销
很多团队上线大模型应用很兴奋,第一周过去一看账单才发现费用远超预期。原因很简单:没有在代码里统计Token消耗。
理论上每次补全响应里都会返回usage字段,包含输入Token数、输出Token数和总Token数。我的习惯是不管什么场景,先把usage打到日志里,存进监控表,每天按模型、按场景、按用户维度汇总。没有这个数据,后面做成本优化就是瞎猜。
预估一次调用成本可以用这个公式:
text复制单次成本 = 输入Token数 × 输入单价 + 输出Token数 × 输出单价
注意输入和输出单价往往不同,输出通常更贵。所以同样是一次调用,让模型说很多废话和让它言简意赅,成本差距会很大。在System Prompt里加上“回答要简洁,不要重复客户问题,不要输出无关寒暄”,是我做过最直接的降本动作。
5.2 语义缓存:命中一次缓存省一次钱
对于客服、问答这类业务,大量用户问题其实是重复的:“怎么退款”“发货要几天”“你们营业到几点”。这些问题的答案完全可以缓存起来,下次直接返回,不用再掏钱调用模型。
但问题不能只拿文本完全相同去匹配,用户表达方式千奇百怪,这时候需要语义缓存。流程是:先把用户问题做向量化,到向量库里找最相似的已回答问题,相似度超过阈值就直接返回缓存答案。缓存里没有的,才调用模型生成,生成完再写回缓存。
这里有一个细节:向量化这一步本身也有成本,但通常比大模型生成便宜得多。而且向量库检索很快,对整体延迟的影响可以忽略。缓存答案要注意时效性,业务规则变化时要能手动清空对应缓存。
5.3 模型分级:不同难度匹配不同模型
同一个业务里不是每个请求都需要最高级别的模型能力。比如“这个订单能退款吗”这种简单问题,用轻量模型甚至静态规则就能处理;“帮我分析这十页合同里的风险点”才需要完整的深度推理能力。
模型分级的核心是流量路由。先由一道简单的分类器判断请求难度,简单的走低成本通道,复杂的走DeepSeek或Kimi这种完整链路。我们内部管这个叫“让API干它该干的活”。
分级还可以结合业务价值来设计:普通用户请求用标准模型,VIP用户请求自动升级到更长上下文、更强推理的模型。用成本换体验,这样做才划算。但分级逻辑一定要做好监控,确保用户无法通过特殊问法绕过分类器,白嫖高成本通道。
6. 实战复盘:一个企业级智能客服系统的完整构建
6.1 需求拆解与系统分层
用一个开发过一段时间的模拟项目X来复盘:某电商平台要做AI客服,目标不是完全替代人工,而是先解决70%的重复咨询。需求拆解之后,核心能力锁定在三块:多轮对话、订单查询、售后政策问答。
系统按五层来搭:
- 接入层:负责SSE流式网关、用户身份识别、会话管理。
- 路由层:判断请求该走DeepSeek、Kimi、工具调用还是语义缓存。
- 工具层:封装订单查询、物流查询、退款进度等内部服务。
- 模型层:管理多个模型入口、超时重试、熔断切换。
- 数据层:向量知识库、会话历史、Token用量日志。
这个分层的好处是每层职责单一。模型换了、工具改了、路由规则变了,互相不牵连。如果某个团队一开始把Prompt、调用逻辑、业务规则全部塞在同一个函数里,后面每改一次需求都要心惊胆战。
6.2 意图识别与工具调用的落地代码
客服系统的核心流程是这样的:用户提问,先查语义缓存,命中直接返回。未命中则进入意图识别,判断用户是要查订单、查物流,还是要问售后政策。
下面的代码展示了“查物流”这个工具的接入方式:
python复制def handle_user_message(user_message: str, session_id: str) -> str:
messages = load_recent_messages(session_id)
messages.append({"role": "user", "content": user_message})
resp = client.chat.completions.create(
model=os.getenv("LLM_MODEL"),
messages=messages,
tools=create_tools(),
tool_choice="auto",
stream=False,
)
msg = resp.choices[0].message
if msg.tool_calls:
for call in msg.tool_calls:
fn_name = call.function.name
args = json.loads(call.function.arguments)
# 统一工具分发
tool_result = dispatch_tool(fn_name, args, session_id)
messages.append(msg) # 先把模型的tool_call消息回传
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(tool_result, ensure_ascii=False)
})
second_resp = client.chat.completions.create(
model=os.getenv("LLM_MODEL"),
messages=messages,
tools=create_tools(),
)
return second_resp.choices[0].message.content
return msg.content
这里有个容易踩的坑:第一轮调用完成后,必须把模型的原始消息msg一起传回第二轮,只传tool结果不传tool_call记录,平台会报错,因为它无法匹配这次工具调用归属于哪条消息。这个细节官方文档里往往一笔带过,但实际开发十有八九会卡这里。
6.3 多轮上下文的裁剪与知识库衔接
多轮对话一旦超过几十轮,历史消息会越攒越大,既浪费Token,模型也可能被旧消息带偏。我用的策略是“最近十轮加法裁剪”:把最近几轮的消息完整保留,更早的消息只保留摘要。摘要可以在会话空闲时异步生成,比如把前20轮对话喂给模型,产出一段话的状态总结,替代原始消息。
知识库方面,Kimi的超长上下文优势在这里体现得最明显。我们把售后政策原文、产品说明书放进向量库,用户提问后先做检索,把最相关的片段拼进上下文,再交给模型组织答案。对于需要逐字对照原文的场景,直接把整份文档塞给Kimi,让模型基于全文回答。
这段链路最深的体会是:知识库不是“塞得越多越好”,检索质量决定回答质量。检索到的内容如果不相关,大模型再厉害也会一本正经地胡说。所以要同时关注检索准确率和最终回答采纳率,而不是只调模型参数。
6.4 上线后看什么指标
系统上线之后不能只看“能不能回答”,要看一组工程指标。
首Token延迟是最影响体验的指标,用户发出消息到看到第一个字的时间要尽量短。总耗时决定接口响应上限。成功率反映接口稳定性。重试率和429频率能暴露限流设置是否合理。每会话Token消耗用来监控成本走势。兜底触发次数如果太高,说明主链路有问题,需要尽快排查。
我在项目里还会额外监控“负向反馈比例”——客服回复后面放一个“没用”按钮,用户点击量除以总回复量。这个指标能比较早暴露出语义理解的问题,比单纯看日志更直接。
最后再分享一个我在这个项目里养成的习惯:上线前专门做一次故障演练,把API Key故意改成错的,把超时时间压到1秒,把并发拉到平台限制的三倍,然后盯着日志看兜底链路能不能扛住。能扛住,才敢说这套系统达到企业级。
做完整条链路之后,我对大模型API应用有了一个完全不同的理解:调用接口只是起点,真正的功夫全在接口之外。DeepSeek和Kimi给了我们两把足够锋利的工具,但怎么把它做成稳定、可控、成本合理的业务能力,靠的还是工程化的那一整套基本功。希望这篇内容能帮你在自己的项目里少走几个来回。
