推理与编排:LangChain、LangGraph 与「捞上下文」

3 阅读9分钟

本稿 · 2026-04-26 · 同专栏 第 3 篇骨架 可成稿后去「骨架」二字或另存 -发布版。)

系列位置第 2 篇已讲本机能转(向量、重排、llama-server 三进程、约 8k)、不重复长命令与 nvidia-smi 教程。本篇进应用层话从哪来、为什么这样接框架

硬件/进程假设(承接第 2 篇):读者已知 对话走 GPU 进程、向量/重排走 CPU 进程 的分工;下文只写请求进业务层之后的顺序。


1. 引子:第 2 篇「能转」,这篇「话从哪来」

先把「能转」验到底。 多进程、三端口起来之后,在接业务代码前,用第 2 篇里的 curl 把对话 / 向量 / 重排各打一条最小请求,确认没接错层、没串端口——这步不偷懒,后面排 bug 会省很多口水。

进了 FastAPI 之后,也先别急。 本项目的习惯是:路由里把「捞到了什么、候选长什么样先打日志或 print 自检,确认时间窗、过滤、是否走向量/重排和脑子里的顺序一致,把这段东西塞进主模型。一上来就端到端出字,出了问题很难分清是召回坏了还是生成坏了。

下面才谈:在强业务里,LangChain / LangGraph 我实际用哪一截、为什么没上全家桶。


2. 工作站里实际用到了什么:LangChain、LangGraph 各一截

先落对照表,再补三句人话(强业务里 LC 还能吃哪几块、为什么我这儿只包一层、Graph 在全文里占多少篇幅)。

2.1 对照表

在做什么与「全家桶 RAG 代理」的距离
LangChain(本项目)RunnableLambda薄封invoke(入参) → dict实验路由统一 I/O 形状不是把记忆 / 全链路检索外包给「链式代理」;强业务状态与策略仍在自己代码里
LangGraph两档:(1)实验向context_langgraph 一类线性图,捞消息 → 过滤 → 排序 → 打日志;(2)主链路与 FastAPI 绑定的 chat 入口 上接「门禁、条件澄清、记忆召回、生成」等一整张图具体 path 以你服务为准,不必与本文逐字一致全链路这档FastAPI + 流式/对照版 放在同一层谈;篇幅上,Graph 集中在「要编排、要条件边、要可观测」的主链路与实验两条线不是全仓库到处塞 StateGraph

与「主链路」的切分(一句):在接有状态的上下文管理、走完整对话闭环之前,我单开了路由只测召回(时间窗、候选、向量/重排是否进 prompt 等)——不参与带门禁与生成的主链;排障、对拍和主链日志混成同一条结论

2.2 强业务里,LangChain 还能用的通常是什么、为什么我只「包一层」

  • 能用的、且相对稳的是「形状与胶水」Runnable、统一 invoke 出参、和 HTTP/自家 ContextStore 的衔接适合做实验路由、对拍时少写样板代码。
  • 刻意少用的是「全家桶语义」:Retriever、Memory、LCEL 全家桶不是不用,而是——一旦会话策略、候选池、门禁、prompt 模板都要按产品改绑死在 LC 的默认抽象上,后面的成本往往高于一开始自己管 get_context_candidates 一类函数。所以本项目是:业务数据与规则自管,LC 只当薄封可替换的编排壳**。
  • 若你的目标是图快、先上线、不在乎后期换骨架完全可以直接上 LangChain 全家桶(Retriever、Memory、现成 RAG/Agent 例),用可接受的耦合时间本文路线是另一种取舍:多写一点自管,换后面改需求时不那么疼

2.3 LangGraph 在本项目里占几成(人话)

  • 就两块图主链全路 + 实验小线性,没有「一张图画满全仓」。
  • 测试/对拍还会多用 LangGraph:按节点打日志、一次性能看清,比一坨 print 好对齐;因此等于「全业务都图驱动」。

3. 「捞上下文」的主逻辑(含门禁、时间窗、重排前的一口坑)

不写 第 2 篇已经讲过的 端口、curl第 2 篇 解决的是:向量 / 重排服务在 HTTP 上怎么喂;本篇解决的是:进业务之后,谁先谁后、进 prompt 之前要剃掉谁。

当前链路的实际顺序(和「有状态的上下文管理」同口径,可抽象成):

  1. 门禁
    先判用户这轮能不能撑起一轮像样对话(信息够不够、是不是有效 turns)。不够就走澄清 / 不急着进主模型——这一点和「主窗口塞进一大段历史」是两条心流,后面还会用到。

  2. 时间窗 + 主上下文
    和上文「只捞约 30 分钟内」一致:主窗口里的上下文也按同一时间策略收束,不是全历史无差别卷入。

  3. 候选
    在窗内,用 get_context_candidates 一类 拉出「可能进 prompt」的消息(是否再 走向量/重排,看开关与业务)。

  4. 重排之前的一口坑实战踩过
    门禁轮往往会在消息流里留下**「第一轮录入/筛选期」的输入**;进重排时若不把这条从候选里剔掉,它会和当前轮用户输入一起进 cross-encoder,排序会歪——所以重排阶段要显式把「门禁录入那一条」筛出去和其余候选一起做 rerank。

  5. 门禁与「要不要再判一轮」
    在相关度/策略允许时,门禁侧可以再判要不要补问缩短卷入在本文展开成 if/else 表。

  6. 重排 → 拼进 prompt → 主推理
    重排完,与当前轮用户消息、系统提示等 拼成主 prompt,交给 llama-server 对话进程 出字(第 2 篇 里那条「生成」的 HTTP)。

与 llama 三服务的关系(一句):业务层决定「捞谁、剃谁、以什么顺序进 prompt」;llama 只负责在约定端口上算 embedding / rerank / chat不替你定 30 分钟、门禁、剔谁不剔谁。

还没做到的:换话题
换话题仍然卡着:业务规则还没到「像成熟产品主窗口」那样,能稳态地判新主题、断旧题又不误伤刚聊一半的内容。后面若能解决,会专门写一篇讲这块;本文只记现状缺口

产品上的参照(主观、非复刻
豆包 一类主窗口上下文感按时间有选择地卷入换话题能接上整体像「老友」在聊——是我这边想逼近的体验方向实现上 仍是自家会话状态 + 规则 + 模型不是 贴牌同款算法。
外发 需弱化具体产品名, 改成「某类 主窗口式对话产品」

阶段总结(承接上文、收束到「不展开」§2~§3 只写到设计口径——门禁、时间窗、重排前剔人、进 prompt 的顺序 落到能让别人照抄的核心业务与字段也无意教复刻LangGraph 在工程里方便按节点对拍、打全日志图/编排是壳换话题、会话策略、谁覆盖谁 仍是业务自管 在这篇和官方文档争细节。


4. llama.cpp 与 vLLM:同一张卷子上,两道大题

这不是「谁更先进」——是 场景你手头有几张卡、能忍受多重的进程栈 的事。

llama.cpp / llama-server 的省心,多半来自「轻、直、可预期」。 同一套工具 CPU、GPU 都能跑,对话进程 不必 和「吃满显存」划等号:本机小显存时往往 一进程 + 一坨 GGUF 就能把事办完,4B 一类量化档一进程工作站/边缘 上常常就很能打;GGUF 直载、独立二进制 部署,没有一整条 Python 推理长栈 挂在耳边,延迟和占用 往往好看。和前面几篇的 三进程(对话 / 向量 / 重排分端口)也天然合拍——分进程、钱和电换体验 那条线不赘述。

vLLM 的强,在另一面: 起服务、占资源 往往就 重一档(典型是 在 GPU 上高吞吐、批处理、PagedAttention/连续批 那一套;光把栈拉满就值得单独规划显存和运维)。HF 权重、PEFT、多 LoRA、类 OpenAI 服务 生态里跟它走的人多——多卡、集群、要当「推理中台」 时,文档和踩坑贴都厚。

你更可能卡在哪llama.cppvLLM
本机/12G/抠门分进程友好:CPU/GPU 可选,默认「一启动就按生产集群胃口吃」更适合 规划好 GPU 后上量
权重与日常姿势GGUF + 量化 为主,少折腾就能对话HF 管线、微调/多路 LoRA 一条线更顺
回复形状本机 llama-server 在带 thinking 的 chat 模板上,常把最终答句中间推理拆到 message.content / message.reasoning_content扩展字段以当前 vLLM 版本行为为准,别默认和 llama 一侧字段名、分路逐字一致

OpenAI 兼容的一口防坑: 都宣称兼容 /v1/chat/completions扩展字段(例如 reasoning_content、流式时 delta 分路别默认全平台、全版本一码通——对接前看各自文档,联调时按实际 JSON 来非流式 一次拿全;流式SSE delta 分路各拼一截,一般不必 自研「从一整段里切 thinking 标签」的解析;客户端若只取 content不等于 模型没走推理,可能是推理在另一路字段里


5. 收束、现状与下一篇

这一套里最吃力的,往往在「本地怎么把环境摆平、服务怎么稳定起来」——部署、分进程、量化与端口、前期踩坑。那一步迈过去之后,线上(本机服务)在跑了,剩下的大头就是按自己业务写规则、接路由、调 prompt 与图编排,没有 一套放之四海而皆准的「业务模板」。

关于窗口与「算不算上线」约 8k 上下文 在这套 12G / 三进程 的实验配置里,目前还不是我心目中的上线定稿——还会做更充分的测试;在后续迭代里,会优先试「换话题」相关的实验与规则(与 §3 里记的现状缺口同一战场), 谈其它指标。

第 4 篇 在系列内是 「链路之外的一刀:语义压缩的独立实验(LlamaIndex + API)」——《链路之外的一刀:语义压缩的独立实验(LlamaIndex + API)》

候选已排好、进主模前 再谈 压缩/再摘要不替代 本篇的「从会话里捞谁」。