人肉LLM:从RLHF到人工反馈,拆解大模型API背后的人力真相
2026/8/28 14:18:17 网站建设 项目流程

这次我们来看一个比较特别的“项目”:ChatTJB。它不是开源模型,也不是推理框架,不需要显卡,不需要 CUDA,甚至连 Python 环境都不是必需品。它的核心卖点是一句话——human-powered LLM,人肉大语言模型。项目方还专门在旧金山(SF)租了一块广告牌来推广这个“产品”。严格说,这是一场关于 LLM 行业的营销行为艺术,但你把它当成一个技术话题来拆,会发现它恰好戳中了我们日常做 LLM 应用开发时最容易忽略的几个问题:大模型 API 到底封装了什么?RLHF 里的“人工反馈”到底有多少人工?如果 GPU、模型权重、推理服务全部消失,一个“LLM 服务”还能不能存在?

这篇文章不打算停留在看段子的层面,我会做四件事。第一,说清楚 ChatTJB 是什么,以及为什么它要在旧金山打广告牌。第二,从工程视角把“人肉 LLM”当作一个伪系统拆开,看看它的架构会长什么样,和真实 LLM 推理链路有哪些对应关系。第三,对照真实的 LLM 部署流程,分析为什么“纯人力推理”没法规模化,以及真实系统里人工环节到底藏在哪些地方。第四,带你自己动手复刻一个最小版“人肉 LLM”演示:用 FastAPI 提供一套 OpenAI 风格的聊天接口,后端把请求丢给真人处理,人工在终端里作答,客户端轮询拿到结果。整个演示不需要 GPU,不需要下载模型文件,纯 CPU 加一个终端就能跑通。

1. 核心信息速览

能力项说明
项目类型LLM 讽刺项目 / 营销行为艺术
核心创意自称“人类驱动的大语言模型”(human-powered LLM)
展示方式旧金山户外广告牌
是否开源材料未说明,按常见 parody 项目判断,未必有完整开源代码
是否需要 GPU不需要,显存占用为 0
是否支持 CPU支持,服务端只是普通 Web 应用
是否提供 API这是讽刺点之一:可以有 API,但后端是人
是否支持批量任务取决于“人工客服”的规模和队列设计
模型文件
适合人群LLM 应用开发者、AI 产品经理、对行业现状感兴趣的技术读者

这里要特别说明:我没有拿到 ChatTJB 官方仓库或完整技术文档,所以本文不写死任何版本号、接口路径、团队信息。重点是它提出的“人肉 LLM”这个思想实验,以及我们从里面能提炼出的工程经验。下面的分析基于项目标题和通用 LLM 行业实践展开,涉及具体数据的地方我都会标注为估算或需自行测试。

2. ChatTJB 是什么:广告牌上的“人肉 LLM”创意

从项目名字看,ChatTJB 显然是冲着 ChatGPT 的命名方式去的。它在旧金山打广告牌,这个行为本身就是一个非常典型的“AI 圈式营销”:最近几年我们见过太多 AI 公司在旧金山、硅谷投放巨幅广告,用极简文案宣告一个可能只存在于演示视频里的新产品。ChatTJB 做的就是把这件事推到极端——它宣称自己就是一个“大语言模型”,只不过驱动这个模型的不是 Transformer、不是 GPU,而是一群真人。你给它发一段问题,背后有人替你组织语言、写回答,然后再通过接口返回给你。

这个创意最聪明的地方在于:它把“AI 产品”里面那层最容易被省略的中间过程直接暴露了出来。我们平时调用 GPT 类接口,看到的是 prompt 进、token 出,中间那一大堆算力、权重、对齐、审核,全部被封装在一个黑盒里。ChatTJB 把这个黑盒换成了实打实的工作人员:你依然发 prompt,依然拿到“模型”回复,但中间的逻辑不是矩阵乘法,而是有人打开问题、思考、打字、提交。

从技术角度看,这个项目并不复杂,甚至可以说没有任何技术创新。但它的价值在于提供了一个极好的思想实验:假如“人工”是唯一可用的推理资源,你该怎么设计一个 LLM 服务?这个问题一旦想清楚,你就明白为什么真实的大模型部署离不开显卡、显存、推理框架和模型文件,也明白为什么 RLHF、数据标注、内容审核这些环节始终绕不开人力。

3. ChatTJB 到底讽刺了什么:LLM 行业的三个盲点

3.1 营销话术与“AI 原生”的荒诞

过去两年,很多产品都在强调自己是“AI 原生”。但实际情况是,有一部分产品只是套了一个聊天界面,后端逻辑仍然是人写的规则;甚至出现过后端藏着真人员工、前端假装是 AI 的案例。ChatTJB 的广告牌把这种荒诞直接演出来了:如果“AI 聊天机器人”的内核可以是一群真人,那“AI 原生”这句话还有什么意义?它讽刺的不是 AI 本身,而是那些把“AI”当标签到处贴、但底层仍然重度依赖人工的商业模式。

对开发者来说,这里有一个很实际的提醒:评估一个 LLM 产品时,不要只看前端演示和营销文案。你要去看它的数据流、人工介入点、成本结构和违规风险。一个接口后面到底跑的是大模型、规则引擎、还是真人外包团队,这直接影响延迟、成本和稳定性。

3.2 RLHF 不是省掉人力,而是最费人力

RLHF(基于人类反馈的强化学习)是今天对齐大模型行为的关键手段。它的流程是先让人类标注员对模型输出排序或打分,再用这些偏好数据训练奖励模型,最后用奖励模型微调策略模型。很多人把 RLHF 当成“让 AI 学会人类偏好”的自动化过程,但 ChatTJB 提醒我们:这个过程的原材料就是人工判断。没有足够多的标注员,就没有高质量的人类偏好数据,对齐效果就无从谈起。

所以“人肉 LLM”并不是对 RLHF 的否定,反而是把 RLHF 里最核心的事实放大了:人工反馈从来都是大模型链路里不可或缺的一环。差别只在于,真实系统里人工反馈被用来训练权重,而 ChatTJB 里人工反馈直接被当成推理过程本身。

3.3 “智能外包”与数据标注的隐形劳动

全球大模型的数据标注环节长期依赖大量人工,很多标注任务发生在低成本地区。标注员看的内容可能涉及暴力、色情、隐私等敏感信息,但往往拿着较低的薪酬,工作强度也不低。ChatTJB 用“人肉 LLM”这种直白到有点残忍的说法,把行业里“看不见的人工劳动”摆到了广告牌上。你平时调用大模型 API 时感觉不到这些人的存在,但这些人的劳动确实以某种方式嵌入了模型的训练和部署过程。

从合规角度说,这一点也值得所有 LLM 开发者注意:如果你在自己的产品里引入人工审核、人工标注或 HITL(Human-in-the-loop)流程,就必须考虑数据处理协议、标注员的隐私保护、以及敏感内容的处理边界。不要只顾着“人工兜底”的效率,却忘了这背后是真实的人在阅读真实数据。

4. 伪系统拆解:一台“人肉 LLM”的架构长什么样

如果 ChatTJB 真的按照“人肉 LLM”的方向做一套可运行的演示系统,它的架构其实不难想象,而且和真实 LLM 推理服务有很多对应关系。我把它拆成四层来看。

4.1 前端与接入层

这一层和普通 LLM API 服务没有区别。用户从聊天框或客户端发起请求,请求通过 HTTP 进入网关。真实系统里这层通常负责鉴权、限流和参数校验;在人肉 LLM 里,这层还要多一个职责:把用户请求转成“人类可读的任务单”,例如把 messages 数组里的最后一条 user 消息提取出来,作为需要人工回答的问题。

4.2 任务队列与调度

真实 LLM 服务靠推理引擎处理并发请求,人肉 LLM 则必须引入任务队列。因为一个真人同一时间只能处理一个请求,如果请求超过人力处理速度,就必须排队。队列的设计直接影响体验:是先来先服务,还是按会员等级插队?要不要设置超时?任务分配是按随机分配,还是按“擅长领域”分流?这些其实和真实后端服务的消息队列设计思路完全一致,只是“消费者”从 GPU worker 变成了人。

4.3 人工 Worker 与知识检索

真实 LLM 推理时,模型权重从显存加载、计算在 GPU 上执行;人肉 LLM 里,Worker 从队列里取任务,然后检索自己的“知识库”——可能是搜索引擎、内部文档、笔记,甚至就是自己的生活经验。这一步相当于真实系统里的 RAG(检索增强生成)。差别在于,真实 RAG 的召回和排序由向量数据库和重排序模型完成,人肉 RAG 的“召回”由人自己决定,“重排序”也凭个人判断。结果就是人肉 LLM 的答案质量方差极大。

4.4 输出审核与质量闭环

真实 LLM 部署时通常会有内容安全审核、敏感词过滤、合规检查等环节。人肉 LLM 同样需要:人工回答完之后,要不要再过一层审核?如果同一个问题被不同 Worker 回答,答案不一致怎么办?要不要建立参考答案库和评分标准?这个“质量闭环”做得好不好,直接决定这个产品能不能被称为一个合格的“服务”。讽刺的是,这部分反而是人肉 LLM 最容易做好的,因为人本身就具备很强的语义理解能力。

把这一整套伪架构映射到真实 LLM 技术栈,可以得到下面这张对应关系表:

真实 LLM 技术栈组件人肉 LLM 的对应实现
推理引擎(vLLM / TensorRT-LLM 等)人工 Worker 的“认知推理”
显存与 GPU人的记忆与理解能力
模型权重文件人脑中积累的知识结构
RAG / 向量检索人工查资料、翻文档
提示词模板给 Worker 看的任务描述和回答规范
内容审核过滤器人工复核或审核员
并发调度任务队列 + 人工排队
Token 计费按人工工时或按条数计费

这张表很有价值,因为它说明了一件事:LLM 服务的一些核心问题,比如质量不稳定、延迟高、并发有限,并不是 GPU 时代才有的,把“模型”换成“人”之后,问题依旧存在。

5. 和真实 LLM 对照:为什么“人力推理”无法规模化

如果把 ChatTJB 当成一个真的要商用的人肉 LLM 系统,它的性能和成本模型会非常难看。下表是“人肉 LLM”和“真实 LLM 在线服务”的典型差异,数据是我基于工程常识给出的量级判断,实际数值需要按具体场景测试。

维度人肉 LLM真实 LLM 在线服务
首字延迟秒到分钟级,取决于人工响应速度数百毫秒到几秒
吞吐能力1 个 Worker 同时只能处理 1 个请求单卡可并发处理多个请求,集群可横向扩展
答案一致性差,换个人答案可能完全不同同一模型、低温参数下相对稳定
扩展方式招人、培训、排班加 GPU、加实例、扩推理集群
成本结构按工时计费,随请求量线性上涨按 Token 计费,单位成本随规模下降
质量稳定性依赖个体水平和状态,波动大依赖模型版本和数据分布,可控性更高
隐私风险真人会看到完整 prompt,泄露面更大服务商能看到数据,但可通过私有化部署缓解
可复现性几乎不可复现固定 seed 和温度时结果可复现

这里最关键的差距是规模化和一致性。真实 LLM 一旦训练完成,推理成本主要就是电费和硬件折旧,加机器就能线性扩展。人肉 LLM 则完全不同:请求量翻一倍,你需要的人力基本也要翻一倍;请求量到了百万级,背后就得是一个几百上千人的外包团队。那个时候,所谓“大语言模型”已经不是模型,而是一个劳动密集型呼叫中心。ChatTJB 的荒诞感正是来自这种反差:我们用“大模型”这个词来强调智能的规模效应,但人力驱动的系统恰恰是最没有规模效应的。

不过,人肉 LLM 也有一个真实模型比不了的优势:它在语义理解、常识判断、伦理边界、上下文推理这些方面,尤其在复杂和模糊场景下,往往比当前大模型更“靠谱”。因为人是真的理解这个世界,而不是在预测下一个 token。这也是为什么真实生产系统里,很多关键决策链路仍然会保留一个人工兜底节点。

6. 真实 LLM 的“人工”藏在哪:从 RLHF 到 Agent 编排

ChatTJB 的讽刺之所以成立,是因为真实 LLM 的链路远比“训练一个模型然后部署”复杂。下面几个环节是人工介入最集中的地方,也是你在读这篇文章时应该重点记住的。

6.1 RLHF 与数据标注

大模型的预训练语料需要清洗、去重、筛选;指令微调需要人工编写指令和回答;RLHF 需要人类标注员对模型输出进行排序。这一整套流程下来,人工成本极高。你在本地部署一个开源模型,只看到下载好的权重文件,但权重背后是大量人工劳动结晶出来的对齐数据。越是符合人类偏好的模型,通常意味着越多的标注投入。

6.2 内容安全审核

上线一个 LLM 应用,内容审核机制几乎不可缺少。很多团队会先用规则和分类模型过滤,然后把风险样本送入人工审核。ChatTJB 那种“真人直接回答”的形态反而省掉了这一层审核,因为真人自己天然具备内容判断力。但真实模型没有这个能力,必须靠对齐和外部审核机制兜底。

6.3 Agent 与 Human-in-the-loop

最近讨论很多的 LLM Agent、MCP(Model Context Protocol)、工具调用,本质上是在让模型自主决策并调用外部工具。但工程实践告诉我们:在涉及支付、下单、删除数据、授权等高风险操作时,通常会嵌入一个 human-in-the-loop 节点,由人来最终确认。这个设计思想恰恰印证了 ChatTJB 的底色:真正关键的最后一步,人类依然不能完全退出。

6.4 RAG 流程中的人工确认

RAG 是目前解决模型幻觉的主流方案,通过检索外部文档给模型提供上下文。但检索结果质量差时,模型照样会一本正经地胡编。所以很多工程团队会在 RAG 链路里加一个人工反馈环节:人工审核检索片段是否相关,再把确认后的内容交给模型生成。这个过程虽然不能称为“人肉 LLM”,但它确实是人工直接参与生成链路的一个典型例子。

7. 复刻最小版“人肉 LLM”:环境准备与启动

下面进入实操环节。我们会做一个最小版的“人肉 LLM”演示系统,完整模拟 ChatTJB 的核心链路:客户端提交问题 → 服务端把请求变成任务 → 人工 Worker 在终端作答 → 客户端轮询拿到结果。

7.1 环境准备

这个演示不需要 GPU,也不需要下载任何模型文件。推荐环境如下:

  • 操作系统:Windows / macOS / Linux 均可
  • Python 3.9 及以上
  • 网络:本地运行,不需要外部模型接口
  • 磁盘:20MB 以内
  • 显存:不需要,占用为 0

唯一需要注意的是端口 8000 不能被占用。如果被占用,可以换成 8010、9000 等。

7.2 安装依赖

需要安装 FastAPI、Uvicorn 和 Requests:

pip install fastapi uvicorn requests

如果国内网络较慢,可以换用镜像源安装:

pip install fastapi uvicorn requests -i https://pypi.tuna.tsinghua.edu.cn/simple

7.3 服务端代码

新建一个文件mini_human_llm.py,写入以下代码:

# mini_human_llm.py # 最小版“人肉 LLM”服务端 # 运行: uvicorn mini_human_llm:app --host 127.0.0.1 --port 8000 import time import uuid from fastapi import FastAPI, HTTPException from pydantic import BaseModel app = FastAPI() # 内存任务表,仅用于演示;生产环境应改用 Redis / Celery 等持久化队列 TASKS = {} class ChatRequest(BaseModel): model: str = "human-1" messages: list[dict] stream: bool = False class AnswerIn(BaseModel): text: str @app.post("/v1/chat/completions") def create_task(req: ChatRequest): task_id = uuid.uuid4().hex # 取出最后一条用户消息作为人工待处理问题 prompt = req.messages[-1].get("content", "") if req.messages else "" TASKS[task_id] = { "prompt": prompt, "answer": None, "status": "pending", "created_at": time.time(), } return {"id": task_id, "status": "pending"} @app.get("/v1/tasks/pending") def list_pending(): return {tid: task for tid, task in TASKS.items() if task["status"] == "pending"} @app.post("/v1/tasks/{task_id}/answer") def submit_answer(task_id: str, ans: AnswerIn): if task_id not in TASKS: raise HTTPException(status_code=404, detail="task not found") TASKS[task_id]["answer"] = ans.text TASKS[task_id]["status"] = "done" return {"status": "done"} @app.get("/v1/chat/completions/{task_id}") def get_result(task_id: str): task = TASKS.get(task_id) if not task: raise HTTPException(status_code=404, detail="task not found") if task["status"] == "pending": return {"id": task_id, "status": "pending", "content": None} return {"id": task_id, "status": "done", "content": task["answer"]}

7.4 启动 API 服务

在项目目录下执行:

uvicorn mini_human_llm:app --host 127.0.0.1 --port 8000

看到类似Uvicorn running on http://127.0.0.1:8000的日志,说明服务启动成功。这个服务本身不消耗 GPU,CPU 占用也很低,几千个请求只是在内存字典里读写。

7.5 启动人工 Worker

再开一个终端,新建worker.py,写入:

# worker.py # 人工 Worker:轮询待处理任务,在终端里人工作答 import time import requests BASE = "http://127.0.0.1:8000" def main(): print("人工 Worker 已启动,等待任务。Ctrl+C 退出。") while True: try: resp = requests.get(f"{BASE}/v1/tasks/pending", timeout=10) resp.raise_for_status() tasks = resp.json() except requests.RequestException as e: print(f"[错误] 无法连接服务:{e}") time.sleep(3) continue if not tasks: time.sleep(3) continue for task_id, task in tasks.items(): print("\n----- 新任务 -----") print("任务ID:", task_id) print("用户问题:", task["prompt"]) answer = input("你的回答: ") try: r = requests.post( f"{BASE}/v1/tasks/{task_id}/answer", json={"text": answer}, timeout=10, ) r.raise_for_status() print("回答已提交。") except requests.RequestException as e: print(f"[错误] 提交回答失败:{e}") if __name__ == "__main__": main()

运行:

python worker.py

Worker 会每隔 3 秒轮询一次待处理任务列表。从这一刻开始,这个系统就是一个真正意义上的“人肉 LLM”:客户端发问题,真人做推理,API 返回结果。

8. 功能测试与效果验证:用 API 走一遍完整链路

8.1 测试目标

验证这套“人肉 LLM”能不能完成最基本的对话闭环:提交请求 → 人工回答 → 获取结果。

8.2 客户端测试代码

新建client.py

# client.py # 客户端:提交问题,轮询等待人工结果 import time import requests BASE = "http://127.0.0.1:8000" def ask(prompt: str, timeout: int = 60) -> str: resp = requests.post( f"{BASE}/v1/chat/completions", json={ "model": "human-1", "messages": [{"role": "user", "content": prompt}], }, timeout=10, ) resp.raise_for_status() task_id = resp.json()["id"] print(f"[client] 任务已提交:{task_id}") start = time.time() while time.time() - start < timeout: r = requests.get(f"{BASE}/v1/chat/completions/{task_id}", timeout=10) data = r.json() if data["status"] == "done": return data["content"] time.sleep(2) raise TimeoutError("等待人工回答超时") if __name__ == "__main__": result = ask("请用一句话解释什么是 RAG?") print("[client] 最终回答:", result)

运行客户端:

python client.py

预期流程是:

  1. 客户端打印任务 ID。
  2. Worker 终端弹出“新任务”,展示用户问题。
  3. 你在 Worker 终端输入答案。
  4. 客户端在下一轮轮询中拿到结果并打印。

判断成功的标准:客户端打印的最终回答内容,和你在 Worker 终端输入的内容一致。整个链路没有调用任何真实大模型接口,驱动它完成的只有一个人。

8.3 用 curl 手动验证

如果你不想写代码,也可以用 curl 完成同样验证:

# 1. 提交对话请求 curl -X POST http://127.0.0.1:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model":"human-1","messages":[{"role":"user","content":"你好,你是谁?"}]}' # 2. 人工 Worker 查看待处理任务 curl http://127.0.0.1:8000/v1/tasks/pending # 3. 人工 Worker 提交回答(把 <task_id> 替换成真实任务 ID) curl -X POST http://127.0.0.1:8000/v1/tasks/<task_id>/answer \ -H "Content-Type: application/json" \ -d '{"text":"我是一个由真人驱动的最小演示系统。"}' # 4. 客户端轮询获取结果 curl http://127.0.0.1:8000/v1/chat/completions/<task_id>

这里每次请求都会走一次完整的人工处理链路,非常适合用来理解任务队列、轮询、异步返回这套 API 设计模式。

8.4 验证过程中的常见失败原因

如果客户端一直拿不到结果,优先检查下面几项:

  • Worker 是否启动?没有 Worker,任务就永远停在 pending。
  • BASE 地址是否一致?服务端、Worker、客户端三处的 127.0.0.1:8000 必须统一。
  • 端口是否被占用?被占用时启动 uvicorn 会直接报错。
  • 是否输错任务 ID?提交答案时 task_id 必须和任务返回的 id 完全一致。

9. “人肉 LLM”的接口 API 与批量任务设计

这套演示的 API 设计故意模仿了 OpenAI 的聊天补全接口,但返回值改成了异步任务模式。为什么要异步?因为

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询