大部分 AI 项目死在 POC 到生产之间。演示环境里模型回答惊艳,上线后却面临延迟超标、成本失控、幻觉频发、无人兜底。AI 落地的核心不是模型选型,而是把概率性组件嵌入确定性系统。本文以一个企业知识问答系统为例,给出从架构到代码的完整落地路径。
第一,只管生成不管检索:模型没有企业私有知识,回答全靠编。第二,没有评估基线:不知道准确率是 60% 还是 90%,无法判断上线是否安全。第三,忽略成本与延迟:每次调用大模型,P99 延迟 8 秒,单次成本 3 毛钱。第四,缺少兜底:模型胡说时无人工接管,直接损害业务。落地方案必须逐一解决这四点。
用户 → API 网关(鉴权/限流) → 编排服务 → 缓存 → 向量检索 → 模型生成 → 输出校验 → 审计
↓
人工兜底队列关键设计:检索先行,无检索结果直接拒答;缓存命中跳过模型;输出校验不通过转人工;全链路审计记录每次调用。
import os, json, hashlib, time
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from openai import OpenAI
from qdrant_client import QdrantClient
import redis
app = FastAPI()
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
qdrant = QdrantClient(url=os.environ["QDRANT_URL"])
r = redis.from_url(os.environ["REDIS_URL"], decode_responses=True)
class Ask(BaseModel):
question: str
tenant_id: str
def embed(text: str) -> list[float]:
return client.embeddings.create(
model="text-embedding-3-small", input=text
).data[0].embedding
def retrieve(question: str, tenant_id: str, top_k: int = 5):
hits = qdrant.search(
collection_name=f"docs_{tenant_id}",
query_vector=embed(question),
limit=top_k,
score_threshold=0.35, # 低于阈值视为无相关知识
)
return [h.payload["text"] for h in hits]
@app.post("/ask")
def ask(body: Ask):
# 1. 缓存:相同问题直接返回
cache_key = f"qa:{body.tenant_id}:{hashlib.md5(body.question.encode()).hexdigest()}"
if cached := r.get(cache_key):
return {"answer": cached, "source": "cache"}
# 2. 限流:每租户每分钟 30 次
rate_key = f"rate:{body.tenant_id}:{int(time.time() // 60)}"
if r.incr(rate_key) > 30:
raise HTTPException(429, "请求过于频繁")
r.expire(rate_key, 60)
# 3. 检索:无相关知识直接拒答,避免幻觉
contexts = retrieve(body.question, body.tenant_id)
if not contexts:
return {"answer": "抱歉,知识库中暂无相关内容,已转人工。",
"source": "no_context", "need_human": True}
# 4. 生成:强制基于上下文,低温度
context = "\n---\n".join(contexts)
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content":
"仅根据给定上下文回答,禁止编造。"
"若上下文不足,回复'无法确定'。"},
{"role": "user", "content": f"上下文:\n{context}\n\n问题:{body.question}"},
],
temperature=0.1,
max_tokens=500,
)
answer = resp.choices[0].message.content
# 5. 输出校验:拒答词检测,触发人工
if "无法确定" in answer or len(answer) < 5:
return {"answer": answer, "source": "low_confidence", "need_human": True}
# 6. 审计与缓存
r.setex(cache_key, 600, answer)
r.hincrby(f"usage:{body.tenant_id}", "tokens", resp.usage.total_tokens)
r.hincrby(f"usage:{body.tenant_id}", "requests", 1)
return {"answer": answer, "source": "llm"}没有评估就没有落地。构建 100 条标注问答集,每次改动跑回归:
def evaluate(testset: list[dict]) -> dict:
correct, refused, wrong = 0, 0, 0
for item in testset:
result = ask(Ask(question=item["q"], tenant_id="test"))
ans = result["answer"]
if result.get("need_human"):
refused += 1
elif item["keyword"] in ans:
correct += 1
else:
wrong += 1
total = len(testset)
return {
"准确率": round(correct / total, 3),
"拒答率": round(refused / total, 3),
"错误率": round(wrong / total, 3),
}上线门槛建议:准确率 ≥ 85%,错误率 ≤ 5%。错误率超标说明提示词或检索有问题,必须调优后再上线。
缓存:高频问题命中缓存,可降低 40% 模型调用。小模型:分类、改写用 gpt-4o-mini,仅复杂生成用大模型。流式输出:首字延迟从 3 秒降到 0.5 秒,体验显著提升。异步批处理:非实时任务走队列,削峰填谷。Token 预算:按租户设置日限额,超限自动降级到规则回复。
任何生产级 AI 系统都必须有人工通道。当检索为空、置信度低、用户点击“不满意”时,自动创建工单:
def create_ticket(tenant_id: str, question: str, answer: str):
ticket = {
"tenant": tenant_id, "question": question,
"ai_answer": answer, "status": "pending",
"created_at": time.time(),
}
r.lpush(f"tickets:{tenant_id}", json.dumps(ticket, ensure_ascii=False))
return {"ticket_created": True}人工处理结果反哺知识库,形成数据飞轮:人工修正 → 补充文档 → 检索增强 → 准确率提升。
总结:AI 落地的胜负手不在模型,而在工程。用检索约束事实,用校验拦截幻觉,用缓存控制成本,用人工兜住底线,用评估守住质量。把概率性智能关进确定性系统的笼子里,AI 才能真正产生业务价值。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。