尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

LLM工程落地指南:从大模型原理到人机协同的FastAPI任务代理实践

LLM工程落地指南:从大模型原理到人机协同的FastAPI任务代理实践 前几天在技术交流群里看到一张海外街头广告牌的照片ChatTJBslogan 写得非常直白——human-powered LLM。乍一看以为是某个新模型上线仔细读才发现这是一次针对 AI 产品营销风格的幽默戏仿。广告牌模拟的是“AI 公司高调宣传大语言模型”的经典画面但核心卖点换成了“背后全是人工”。这个场景放在今天的 AI 语境下其实非常有意思。LLM 技术已经渗透到对话、搜索、编程、运营、客服等无数场景铺天盖地的广告都在强调“AI 驱动”“模型能力”。但当广告牌把“human-powered”写出来的时候它反而戳中了一个工程现实很多声称模型自动完成的产品真正落到生产环境时背后往往还有大量人工标注、人工审核、人工兜底这就是业界常说的 human-in-the-loop人在回路。本文不打算讨论这个广告牌本身是营销还是行为艺术而是借这个话题系统梳理 LLM 应用开发中的几个关键问题LLM 是什么、为什么大模型产品不能只靠“调用一个模型”、人机协同在工程上如何设计、以及一个带人工兜底的 LLM 任务代理服务该如何从零搭建。无论你是刚开始接触 LLM 的初学者还是已经在做 Agent / RAG 相关项目的开发者这篇文章都能给你一套可落地的思路和一份能直接运行的参考代码。1. 从一块海外街头广告牌说起ChatTJB 与 LLM1.1 ChatTJB一场关于“AI 背后是谁”的戏仿广告牌上的 ChatTJB 并不是真实产品更像一个带着嘲讽意味的创意表达。它模仿了当下常见的大模型产品宣传方式但把“AI 自动”“大规模训练”“智能体”这些热词全部替换成了“人肉驱动”“人工回答”。这种反差感之所以能引发讨论是因为它精准映射出了普通用户和技术从业者共同感受到的一种落差对外营销时产品讲的是“模型推理”“自动生成”“全网首发的新架构”对内落地时团队忙的是“标注数据”“人工审核”“badcase 修复”“规则兜底”。从工程视角看这并不矛盾。LLM 确实能自动化完成大量文本生成、理解、总结、改写任务但它依然是一个概率模型存在幻觉、知识过时、标准不稳定等问题。医疗建议、金融解释、法律条款、客户投诉等高敏感场景直接让模型“自动答复”风险很高必须加入人工审核或人工修正环节。广告牌把“人工”堂而皇之地写进标语本质是提醒大家无论模型能力多强一个可交付的产品永远不能只有模型本身。1.2 LLM 到底是什么为什么绕不开LLM 的全称是 Large Language Model中文一般叫大语言模型。通俗理解它是基于海量文本数据训练出来的深度神经网络模型核心任务是预测一段文本中下一个 token 出现的概率。当前缀信息足够丰富、模型参数规模足够大、训练数据足够充分时这种“概率预测”就会表现出接近人类的文本理解与生成能力。从应用角度LLM 能做的事情很多对话问答像聊天机器人那样回答问题内容生成写文章、写邮件、生成营销文案代码辅助补全代码、解释代码、根据注释生成函数信息抽取从文本中提取结构化信息智能体控制把大模型作为 Agent 的“大脑”编排工具调用和任务执行链。在今天的技术环境里LLM 已经变成一个“基础能力组件”。开发者不需要从零训练一个模型大概率是通过 API 调用现成的大模型或者在开源模型基础上做微调、部署。但“调用 API”和“完成一个可靠的产品”之间还有很大的工程距离。1.3 广告牌给工程落地留下的三个提醒结合 ChatTJB 的创意再去看 LLM 项目落地有三个提醒值得记下来第一LLM 不等于“全自动”。模型只是流程中的一个环节真正可靠的系统需要在模型前后增加输入校验、输出校验、规则引擎、人工审核等机制。第二人工介入不是落后的标志。在很多业务里人工介入越少说明系统越成熟但强制把人工介入率压到零反而可能带来严重的体验或合规风险。人机协同是生产环境里最常见的工程形态。第三面向消费者的 AI 产品需要守住透明底线。如果产品本质上依赖大量人工处理却对外宣称“全程 AI 自动”不仅是信任问题还可能涉及虚假宣传或合规风险。合法的做法是明确告知用户哪些环节由模型完成哪些环节有人工参与。2. LLM 应用开发中的几个高频关键词如果你最近在关注 LLM 相关技术一定逃不过这几个词推理精度、Agent、RAG、MCP、提示词工程。它们不是并列关系而是分别解决不同层面的问题。2.1 从模型精度到推理成本FP16、FP32、BF16在部署模型或使用开源模型时经常会看到 FP16、FP32、BF16 这样的精度标记。它们指的是模型权重和计算时的浮点数存储格式直接影响显存占用、推理速度和数值稳定性。FP3232 位浮点完整单精度数值范围大精度高但占用的显存也最大。一般情况下FP32 多用于模型训练或作为精度对照基准。FP1616 位浮点半精度显存占用约是 FP32 的一半推理速度更快。但 FP16 的动态范围较小训练过程中容易出现精度溢出所以早期模型训练时使用 FP16 往往需要配合损失缩放。BF16Brain Floating Point也是 16 位但把更多 bit 分给了指数位动态范围接近 FP32因此比 FP16 更稳定是目前很多大模型训练和推理的主流选择。更低精度量化比如 INT8、INT4通过把权重从浮点数压缩到整数进一步降低显存和带宽压力。缺点是精度会进一步损失通常需要做校准和评估。版本和工具链更新很快不同框架在不同硬件上对精度的支持也有差异实际项目里需要根据 GPU 型号、模型大小、延迟要求、准确率指标来综合选择。这里不需要背参数重点是记住一个结论显存紧张的推理环境优先考虑 BF16 或量化训练环境优先保证数值稳定性且所有精度变化都要接受评测集验证。2.2 Agent、RAG 和 MCP分工与合作很多刚接触 LLM 的同学会把 Agent、RAG、MCP 混在一起其实它们解决的是不同问题。Agent智能体是一种应用范式。普通 LLM 调用是“用户问一句模型答一句”而 Agent 让模型具备目标拆解、工具调用、结果判断、多轮迭代的能力。比如“帮我查一下今天的天气”Agent 可以把这个任务拆成“定位城市”“调用天气 API”“整理回答”三步并循环执行直到任务完成。RAGRetrieval-Augmented Generation检索增强生成解决的是“模型不知道私有知识”和“幻觉”问题。模型训练完成之后知识是固定的但企业内部的文档、数据库、业务规则每天都在变。RAG 的做法是先把外部知识切成片段并做向量化用户提问时先检索最相关的片段再把片段拼进提示词交给模型生成。这样模型不再是“凭空回答”而是在给定资料的基础上作答准确率和可解释性都会好很多。MCPModel Context Protocol模型上下文协议是一种工具接入协议。它解决的是“Agent 如何统一调用外部工具”的问题。以前每个 Agent 项目都要自己实现一套工具调用协议MCP 通过标准化接口让模型可以更方便地连接到数据库、浏览器、代码仓库、第三方服务等。简单来说RAG 让模型“有话可说”Agent 让模型“有事可做”MCP 让 Agent 的工具“插拔方便”。它们可以独立使用也可以在同一个项目里组合出现。2.3 “调用 API”不等于“完成交付”对很多刚接触大模型的开发者来说第一段代码往往是从 API 调用开始的response client.chat.completions.create( modelyour-model, messages[{role: user, content: 你好}] ) print(response.choices[0].message.content)代码确实很短几分钟就能跑通。但真实业务里一段能上线的代码远比这个复杂因为你需要考虑模型响应超时怎么办模型返回内容为空或者格式不对怎么办用户输入包含敏感词怎么办模型输出涉及免责声明或合规风险怎么办高并发时 API 限流怎么办模型升级后回答质量下降怎么办这些都不是“模型能力”能单独解决的而是典型的工程问题。所以下文会用一个具体项目演示如何把“模型自动处理”和“人工审核兜底”组合成一个可运行的服务。3. 人机协同LLM 生产落地绕不开的一环网上有一个很流行的说法AI 不会替代人但会用 AI 的人会替代不会用 AI 的人。在 LLM 工程落地中这句话可以写得更具体——纯自动化无法覆盖所有边界合理的人工介入能让系统更快上线也更安全。3.1 哪些业务场景必须人工参与从实践来看下面几类场景几乎必然需要人工参与客服与售后模型先生成回复人工审核高风险或情绪激烈的会话。医疗与法律模型只能提供参考建议最终结论必须由专业人士确认。金融与财务涉及金额、合同条款、投资建议的内容模型输出必须经过复核。内容安全模型生成的文本需要经过敏感词过滤、分类模型初筛、人工运营终审。数据标注与评测持续收集 badcase人工标注后反哺模型微调或 Prompt 优化。这并不意味着“模型没有用”。恰恰相反模型承担了 90% 的常规工作量人工只需要处理剩余 10% 的边界情况。整体成本可能比纯人工低一个数量级又比纯自动化可靠得多。3.2 事前审核与事后复审两种兜底模式人机协同中人工介入的时机决定了整个系统的延迟和安全等级。事前审核先审后发是指模型生成结果后必须先经过人工确认才能返回给用户。这种模式安全性最高适合医疗建议、金融结论、对外正式回复等内容。缺点是延迟偏高不适合对实时性要求极高的场景。事后复审先发后审是指模型结果先返回给用户同时异步推送到人工后台进行复审发现问题再处理。这种模式体验好但风险窗口更大适合低风险内容或用户能理解“AI 生成可能存在偏差”的场景。实际项目中也可以把两者混合先用规则引擎识别高风险请求只有命中风险才走事前审核低风险请求直接返回但进入抽样复审队列。3.3 透明披露技术可行不等于可以隐瞒这里必须要强调一个合规底线任何产品如果实际使用了人工参与却对外宣称“完全由 AI 自动完成”都是不合适的。广告牌之所以是“戏仿”正是因为它把潜规则摆到了台面上。正确的做法是什么在产品说明中明确标注本服务由大模型提供初步回答部分场景会有人工审核。在对话界面中可以提示“内容由 AI 生成仅供参考”。对人工介入的会话保留审计日志便于追溯。透明披露不会降低产品价值反而会建立用户信任。尤其当系统偶尔出现人工介入延迟时提前告知比事后解释更容易被接受。4. 完整实战用 FastAPI 搭建带人工兜底的 LLM 任务代理服务下面进入代码环节。我们要实现一个任务代理服务它接收用户请求先调用 LLM这里用 mock 函数模拟然后根据配置决定是否进入人工审核流程。整个过程使用异步任务和任务 ID 查询结果。这个示例的核心价值不是“模拟人工冒充 AI”而是演示人机协同的工程骨架。真实项目中人工处理往往通过工单系统、审核后台或标注平台对接但状态流转和接口设计思路是相通的。4.1 需求与流程拆解先明确需求用户提交 prompt服务为每个请求生成一个 task_id。后台任务调用 LLM 生成结果。如果 mode 是 human_review则进入人工审核流程人工会修改或补充最终结果。用户可以通过 task_id 轮询结果状态包括queued、processing、pending_review、completed、failed。流程可以用文字描述如下客户端 POST /requests提交 prompt 和 mode。服务端创建任务返回 task_id。后台任务执行调用 LLM → 等待人工处理可选→ 更新状态。客户端 GET /requests/{task_id} 获取最新状态和结果。4.2 项目结构与环境准备项目结构如下llm-proxy-demo/ ├── app.py ├── requirements.txt └── README.md本示例使用 Python 3 和 FastAPI依赖较少。安装命令如下pip install fastapi uvicorn pydantic版本请根据当前环境调整。本文重点是演示设计思路不绑定某个固定版本。如果你在局域网或离线环境可以直接用 pip 安装依赖后运行。4.3 核心代码实现完整代码如下请保存为app.py。# app.py 带人工兜底的 LLM 任务代理服务演示。 说明 - 本示例使用内存字典保存任务状态仅用于学习演示。 - 生产环境请使用 Redis / MySQL / 消息队列并补充鉴权、审计、日志等能力。 - 如果产品面向真实用户请务必如实披露人工参与情况避免误导用户。 import time import uuid from typing import Optional from fastapi import BackgroundTasks, FastAPI, HTTPException from pydantic import BaseModel, Field app FastAPI(titleLLM Proxy Demo) # 内存任务表仅用于演示 tasks: dict[str, dict] {} class TaskRequest(BaseModel): prompt: str Field(..., min_length1, description用户输入) mode: str Field( auto, descriptionauto 表示纯模型处理human_review 表示需要人工兜底, ) class TaskCreateResponse(BaseModel): task_id: str status: str message: str class TaskResult(BaseModel): task_id: str status: str output: Optional[str] None llm_output: Optional[str] None reviewed_by_human: bool False def call_llm(prompt: str) - str: 模拟 LLM 调用。 真实项目中替换为 OpenAI SDK、本地模型服务或企业内部模型网关即可。 这里用固定延时加模板字符串模拟模型响应。 time.sleep(1.5) return f[mock-llm] 收到问题{prompt[:40]}... def human_process(task_id: str) - None: 模拟人工审核与修改。 真实项目中这里可能连接审核工单系统、标注平台或内部审核后台。 time.sleep(2) llm_output tasks[task_id].get(llm_output, ) tasks[task_id][output] ( llm_output \n[human-review] 已完成人工复核并补充修正。 ) tasks[task_id][reviewed_by_human] True def process_task(task_id: str, req: TaskRequest) - None: tasks[task_id][status] processing try: llm_output call_llm(req.prompt) tasks[task_id][llm_output] llm_output if req.mode human_review: # 进入人工审核注意真实系统通常不会在后台任务里同步阻塞人工审核 # 而是把任务推给审核平台再由审核平台回调更新状态。 # 这里为了演示方便直接同步模拟人工处理。 tasks[task_id][status] pending_review human_process(task_id) else: tasks[task_id][output] llm_output tasks[task_id][status] completed except Exception as exc: tasks[task_id][status] failed tasks[task_id][error] str(exc) finally: tasks[task_id][updated_at] time.time() app.post(/requests, response_modelTaskCreateResponse) def create_task( req: TaskRequest, background_tasks: BackgroundTasks ) - TaskCreateResponse: task_id uuid.uuid4().hex now time.time() tasks[task_id] { task_id: task_id, status: queued, prompt: req.prompt, mode: req.mode, output: None, llm_output: None, error: None, reviewed_by_human: False, created_at: now, updated_at: now, } background_tasks.add_task(process_task, task_id, req) return TaskCreateResponse( task_idtask_id, statusqueued, message任务已受理, ) app.get(/requests/{task_id}, response_modelTaskResult) def get_task(task_id: str) - TaskResult: task tasks.get(task_id) if not task: raise HTTPException(status_code404, detailtask not found) return TaskResult( task_idtask_id, statustask[status], outputtask.get(output), llm_outputtask.get(llm_output), reviewed_by_humantask.get(reviewed_by_human, False), ) app.get(/health) def health_check(): return {status: ok}这段代码里用到几个值得注意的工程点BackgroundTasks让任务在后台执行接口可以立刻返回 task_id避免请求长时间挂起。任务状态用字符串枚举表达方便日志检索和前端轮询。llm_output和output分开保存便于观察模型原始输出和人工修正后的差异。人工审核的结果通过布尔字段reviewed_by_human标记后续审计更容易。4.4 运行与验证启动服务uvicorn app:app --reload --port 8000看到Uvicorn running on http://127.0.0.1:8000后打开另一个终端先用 curl 提交一个人工审核任务curl -X POST http://127.0.0.1:8000/requests \ -H Content-Type: application/json \ -d {prompt:请用一句话解释什么是 LLM,mode:human_review}预期返回类似{ task_id: a1b2c3d4e5f6..., status: queued, message: 任务已受理 }注意保存返回的 task_id。然后查询结果curl http://127.0.0.1:8000/requests/a1b2c3d4e5f6...在任务处理过程中可能会看到status为processing或pending_review。几秒后再次查询会看到status为completed且reviewed_by_human为trueoutput中包含人工复核的标记。也可以写一个简单的 Python 客户端脚本演示完整轮询过程# client.py import time import requests resp requests.post( http://127.0.0.1:8000/requests, json{prompt: 什么是 RAG, mode: human_review}, ).json() task_id resp[task_id] print(task_id:, task_id) for _ in range(10): time.sleep(1) result requests.get(fhttp://127.0.0.1:8000/requests/{task_id}).json() print(result[status], reviewed_by_human:, result.get(reviewed_by_human)) if result[status] in (completed, failed): print(----- output -----) print(result.get(output)) break运行方式python client.py预期输出中会看到状态从processing变为pending_review最后变成completed并且最终输出里有[human-review]标记。4.5 生产环境改造点上面的示例可以直接跑通但离生产环境还有距离。如果你要在此基础上做正式项目建议按下面几个方向改造存储层把内存字典替换为 Redis 或 MySQL任务状态才能跨实例共享。人工审核平台把“同步模拟人工处理”改为“推送任务到审核平台”审核平台处理完成后回调更新状态。鉴权与限流接口增加 API Key、签名、频控策略。模型接入把call_llm替换为真实模型 API并加入超时、重试、异常分类。日志与审计记录每一次模型调用、人工介入、状态流转便于溯源。5. LLM 项目高频问题与排查思路在实际开发中LLM 项目的问题往往不是“模型不好”而是“系统没有把模型不好的一面兜住”。下面是一份常见问题排查表。问题现象常见原因解决思路接口响应超时模型推理慢、网络抖动、上游限流设置超时时间增加重试考虑异步任务 轮询模式回答出现幻觉模型对隐私知识不了解或提示词没有给出足够约束引入 RAG检索相关资料后生成对高风险输出增加人工审核结果不稳定temperature 设置偏高模型随机性大调低 temperature固定 seed对输出做二次校验长文本处理时内存溢出上下文过长显存或 token 超限截断、摘要、分块处理限制 max_tokens用户察觉背后是人工服务产品未做透明披露体验不一致提前披露人工审核机制优化人工处理延迟模型效果不错但成本很高提示词太长、每次请求重复计算、并发不足增加缓存压缩提示词批量推理按场景选择更经济的模型排查时建议遵循一个顺序先复现再定位最后修复。复现时收集完整的请求参数、模型输出、时间戳定位时区分是模型层问题、工程层问题还是数据层问题修复后加入回归用例避免同一个问题反复出现。比如遇到“回答质量下降”不要急着换模型。可以先看最近是否更新了提示词模板再看是否有新业务数据没有进入 RAG最后再评估当前模型版本是否需要升级或微调。6. LLM 应用工程化的最佳实践6.1 提示词工程先行提示词是 LLM 应用最基础的控制手段。同样的模型在不同的提示词下表现可以差距很大。一个结构化提示词通常包含几个要素角色设定、任务说明、输入数据、输出格式、约束条件、示例。一个参考模板如下你是一位资深技术编辑擅长用通俗语言解释复杂概念。 请根据下面的用户问题输出一段不超过 200 字的回答。 要求 1. 先给出核心定义。 2. 再举一个生活化例子。 3. 最后给出一个使用建议。 如果问题涉及不确定信息请明确说明“需要进一步核实”。 用户问题{{question}}提示词不要追求越长越好关键是信息明确、格式可控。高频变化的提示词建议放到配置中心不要硬编码在代码里。这样业务人员调整表达时不需要重新发版。6.2 模型层抽象与降级生产环境不能只有一个模型。你需要一层抽象把模型调用封装成统一接口然后针对不同场景配置不同模型自动 fallback。下面是一个极简封装思路# llm_client.py class LLMClient: def __init__(self, primaryNone, fallbackNone): self.primary primary self.fallback fallback def generate(self, prompt: str) - str: try: return self._call(self.primary, prompt) except Exception: if self.fallback: return self._call(self.fallback, prompt) raise def _call(self, model, prompt): # 替换为真实模型 API 调用 return f[{model}] response更完整的降级链路应该包括规则模板 → 模型 → 人工兜底。当模型调用连续失败时可以返回预设的兜底话术再异步通知人工跟进。6.3 评测与可观测性LLM 项目上线后最容易犯的错误是“只看功能跑通不看质量变化”。模型是非确定性的今天效果好不代表下周效果好新版本可能在某些主题上变差。建议做好三件事建立一份评测集至少覆盖 50 到 200 条典型业务问题。每次模型升级或提示词变更时跑一遍评测集对比准确率、可读性、合规通过率。生产日志记录请求参数、模型版本、token 数、延迟、人工介入率、用户反馈。人工介入率是一个很值得关注的指标。它代表系统中有多少比例的内容被人工修正。比例过高说明自动质量不达标比例长期接近零也要警惕是不是边界情况没有被覆盖而不是系统真的完美。6.4 安全与合规底线最后是最重要的一部分安全与合规。最小权限原则Agent 如果需要调用数据库或第三方系统必须遵循最小权限不能因为“演示方便”而把所有权限放开。敏感信息保护用户输入可能包含手机号、地址等个人信息。日志脱敏、数据加密、访问控制都要提前规划。输出过滤模型输出应经过敏感词过滤、内容安全检测必要时接入人工审核。审计追溯人工介入的会话必须保留完整记录包括谁在什么时间修改了什么内容。生产变更涉及数据库更新、配置变更、模型切换时先在测试环境验证做好备份和回滚方案。这里多说一句AI 生成内容的法律责任仍在不断完善中。作为开发者我们可以通过透明披露、人工审核、日志审计等方式降低风险但这不能替代合规团队给出的正式意见。如果业务涉及医疗、金融、法律等强监管领域上线前一定不要省掉合规评审。7. 结语把“人工”放回正确的工程位置回到开头那块广告牌。ChatTJB 用幽默的方式提醒了我们一个事实在大模型时代“人工”并不是一个见不得光的词。相反优秀的人机协同设计往往决定了产品能否稳定运行。本文从 LLM 的基础概念讲起介绍了 Agent、RAG、MCP、推理精度等高频关键词也讨论了人机协同的必要性和两种兜底模式。实战部分用一个 FastAPI 服务演示了“模型自动处理 人工审核”的任务代理流程核心代码可以直接下载运行。最后给出了高频问题排查表和工程化最佳实践。如果你准备在自己的项目里落地 LLM建议先按这个顺序实践跑通上面的 FastAPI 示例把任务状态流转理解清楚。用真实 LLM API 替换call_llm并加上超时与重试。把人工审核从“同步模拟”改成“后台工单系统 回调”。建立评测集和日志监控持续观察人工介入率。技术栈迭代很快模型版本会不断更新但“模型 工程 人机协同”这个底层框架不会过时。把每一步做扎实比追逐新框架更能让你在 LLM 项目中走得更远。如果这篇笔记对你有帮助可以收藏备用也欢迎在实际项目中试试这段示例代码。
返回列表