找回密码
立即注册
搜索
发回帖 发新帖

5048

积分

0

好友

646

主题
发表于 1 小时前 | 查看: 4| 回复: 0

看到标题这段心声,感觉还挺有道理。如果不打算往上爬,苟在 2-2 到 3-1 这一段性价比确实最高,尽量多存款,多靠近 AI。再往上走,过程很累,成功率三成左右。

终端对话截图:讨论字节跳动职级体系、2-2/3-1性价比与2024年职级改革

2-2 算是资深工程师,项目里的主力;3-1 再上去一档,开始带小团队、扛一部分方向判断。这两档的共同点是收入已经到行业高位,但责任还没质变,自己的产出自己能控制,也不用为别人的产出和跨部门博弈买单。

再往上游戏规则就变了,需要从「把事做成」切换成「管人、争资源、向上管理」。时间被会议和资源协调占满,个人可控产出反而下降,心也更累。

靠近 AI、多存款,确实是目前大多数人的最优解,也能在行业波动时给自己留出更多选择空间。如果正在考虑职业规划,这两个方向值得重点权衡。

拿字节来说,C 端是豆包,模型是 Seed,编码工具有 Trae,算力和云服务在火山引擎。除此之外,还有很多人不太注意的一块:字节在 AI 编译器方向也有不少开源项目,ByteIR 是基于 MLIR 的模型编译方案,Triton-distributed 和 Flux 都在解决计算和通信怎么重叠的问题。

字节AI业务与开源项目地图:从豆包、Seed到ByteIR、Flux的技术栈布局

豆包工作是我最近一个月一直在用的产品。不能说能力特别强,和 Codex、Claude 在某些方面,尤其是做事能力上还有差距,但能做的事确实越来越多。

豆包工作界面截图:Remotion视频Skill修改与静帧验收

我甚至开始用豆包工作制作视频,效果还不错。AI 是洪水猛兽,也是能力边界的放大器。

它能让你在不懂编程的情况下开发出产品,也能在顶级老师辅助下搞懂以前学不动的知识。不过要学的东西也多到应接不暇,人很容易累。

所以我的建议是:能学得进去就多学一点,学不进去的时候就照顾好身体。

让我们开始今天的硬核内容,主要围绕 RAG 展开。看完你会发现,和网上天天传的「RAG 已死」有很大区别,这块往深处研究,东西还挺多。

01、做过哪些 AI 项目?

「最早做的是派聪明,一个企业级的 RAG 知识库。我做的是文档上传、解析、切分、向量化,以及问答时的混合检索。技术栈是 Spring Boot 3 加 Elasticsearch 8,Embedding 和重排序用阿里的 text-embedding-v4 和 gte-rerank-v2,大模型用的 DeepSeek,上传后的解析任务走 Kafka 异步处理,文件存在 MinIO 里。」

派聪明从上传到问答的流程图:文档入库与在线问答两阶段

「第二个项目是 PaiCLI,一个 Java 写的终端 Agent。里面有 ReAct 循环、Plan-and-Execute 任务图、多角色协作三种执行模式,工具调用、代码检索、MCP 接入都是自己实现的。技术栈是 Java 17 加 OkHttp,终端界面用 JLine,代码检索用结巴分词加 SQLite,Java 文件的语法树解析用 JavaParser,Git 快照回滚用 JGit。」

如果对这类终端 Agent 开发 感兴趣,ReAct、工具调用和 MCP 是绕不开的核心能力。

02、RAG 的相关性如何计算?

「派聪明是按分工来的,一次检索算两路分:向量一次、关键词一次,两路合起来之后还要再算一次。」

「向量算的是余弦相似度。用户的问题先用 text-embedding-v4 转成 2048 维向量,Elasticsearch 里存文档向量的字段是 dense_vector,相似度函数配的是 cosine。」

「派聪明的召回窗口按请求的 topK 乘 30 算,上限 300 条。topK 默认是 5,所以向量这一路一次取 150 条。KNN 查询里还有一个候选数,设成召回窗口的两倍,也就是 300。这个参数管的是 HNSW 图在搜索时每层保留多少个候选节点,给大一点结果更接近真实最近邻,代价是搜索变慢。权限过滤放在 KNN 内部做预过滤,先过滤再找最近邻,不然召回 150 条里可能有一百多条这个用户无权查看,过滤完就剩不下几条了。」

「这个倍数定得比较大,是因为召回阶段漏掉的文档,后面两步都补不回来。RRF 只能给已经召回进来的文档排序,精排只能在 RRF 的前 50 条里挑。第一步没取到的文档,后面再怎么算都不会出现。所以召回这一步宁可多拿一些,把筛选压力留给后面两步。」

两路召回并行执行流程图:向量KNN与关键词BM25召回后融合

「关键词算的是 BM25。这两路是并行发出去的,用 CompletableFuture 同时执行。两路里任何一路出了问题,就用另一路的结果继续往下走,不让这次检索失败。」

「两路结果拿回来之后,向量分和 BM25 分没法直接相加。一个是零到一的相似度,另一个是 BM25 分数,没有上界,两个数字不在同一个尺度上。做归一化也不靠谱,min-max 归一化要用这一批结果里的最大值做分母,同一篇文档换个问题去检索,分母变了,它的分数也跟着变,这个分数就没法用来做阈值判断了。」

「业界另一种常见做法是加权求和,两路分数各自归一化之后按权重相加,比如向量占七成、关键词占三成。它的麻烦在于这两个权重只能拿评测集一点点试,而且换一批文档、换一个 Embedding 模型就得重新试一遍。RRF 只用名次,没有需要调的权重。」

「所以派聪明用的是 RRF,倒数排名融合。只看文档在每一路里排第几名,每一路贡献的分数是一除以 k 与名次之和,k 取 60。一篇文档的总分就是它在两路里的贡献之和。Elasticsearch 的向量分数在这一步没有被读取,用的只是名次。」

「k 取 60 的作用是压平头部差距。如果不加这个 k,第一名贡献 1 分,第二名 0.5 分,差了一半,相当于完全相信单路排序。加上 60 以后,第一名是 1/61,第二名是 1/62,两者很接近。一篇文档要排在前面,得在两路里都靠前,只在一路里排第一是不够的。这正是混合检索想要的效果:两种召回方式都认可的文档才最可信。」

「RRF 解决了排序,但它给出的分数无法表达相关程度。1/61 加 1/62 这个数字只说明这篇文档在两路里都排得很靠前,没法告诉我这篇文档到底对不对得上用户的问题。所以融合之后还要再算一次分。派聪明把 RRF 结果的前 50 条交给 gte-rerank-v2 做精排,每条文本截断到 2000 个字符,模型返回一个相关性分数,最终的排序和过滤都用这个分数。」

RRF融合与rerank精排流程图:两路排名、名次融合与相关性精排

「精排用的是交叉编码器。把问题和文档拼在一起送进模型,模型能看到两者之间逐词的对应关系,所以判断得更准。代价是没法预先计算,有多少候选就要算多少次。50 条是一个能接受的量。」

「精排要再调用一次模型,所以它也有超时和降级。派聪明在请求入口生成了一个截止时间,走到精排这一步,剩余时间不足 2 秒就跳过精排,直接用 RRF 的顺序返回。」

03、关键词相关性如何计算?

「关键词用的是 Elasticsearch 默认的 BM25,它算出来的是三个因子相乘的结果。」

「最直观的因子是词频。一个词在文档里出现得越多,这篇文档越可能是在讲这个词。但词频不能一直线性加分,出现 20 次和出现 100 次,相关程度并没有差 5 倍。所以 BM25 用参数 k1 控制加分饱和速度,默认值 1.2。词频到一定次数之后再增加,分数涨幅就很小了。」

「光看词频会被常见词带偏,因为出现次数最多的往往是『的』这类词。所以每个词的贡献还要乘上逆文档频率。一个词在整个索引里出现在越少的文档中,它的区分能力越强,权重就越高。用户问『派聪明的向量维度是多少』,向量和维度这两个词只出现在少数文档里,权重高;『的』几乎每篇文档都有,权重接近零。」

「这两个因子算完,长文档还是占便宜,因为它包含的词多,命中关键词的机会天然就大。所以 BM25 最后要按文档长度相对于平均长度做一次折算,参数 b 默认 0.75。给到 1 是完全按长度折算,给到 0 是完全不管长度。」

BM25三个核心因子图解:词频饱和、逆文档频率与长度归一化

「派聪明这两个参数用的是默认值 1.2 和 0.75。知识库里的文档被切分成 512 个字符的分块,长度本来就比较均匀,长度归一化起的作用不大;一个关键词在 512 个字符里重复出现几十次的情况也很少,饱和速度调了意义不大。」

「中文这边还有一层分词。BM25 算的是词,中文得先把句子切分成词。派聪明的文本字段建索引时用 ik_max_word,查询时用 ik_smart,两边不一样。建索引用细粒度,把『派聪明的向量维度』切分成『派、聪明、派聪明、向量、维度』这些词都存进倒排索引,能被更多种问法命中;查询用粗粒度,避免用户的问题被切得太碎,碎词命中的都是不相关文档。」

建索引与查询使用不同分词粒度示意图:ik_max_word与ik_smart

「默认的 match 查询,多个词之间的关系是或,只命中一个词的文档也会被召回。假如用户提问里有一半是没有信息量的词,光靠 BM25 的名次,前几名很可能是只命中某一个词的文档。所以 BM25 在派聪明里的职责只是提供一路名次,它和向量召回互相补充,谁也不单独决定结果,最终由精排模型来定。」

「关键词检索还有一个绕不开的问题:分块里可能根本不出现那个关键词。一份文档按 512 个字符切开,中间某一段写的是『该参数默认开启,建议不要修改』。这个参数到底是哪一个,只有上一段才知道。用户按参数名去搜,这一段的倒排索引里没有这个词,BM25 召不回来,向量也召不回来。」

「派聪明的办法是入库时给每个分块生成一句上下文描述,说明这一段在整篇文档里讲的是什么、主语是谁,拼在分块正文前面,一起参与向量化和倒排索引。开启这个功能以后,关键词查询也从单字段匹配换成多字段匹配,分块正文和上下文描述各算一次 BM25 再合起来。代价是入库时每个分块都要多调用一次大模型,所以这个功能默认关掉,只在对准确率要求高的知识库上开。」

04、最终相关性分数的值域是什么?

「这个要分情况,因为派聪明返回的分数字段在三种模式下来源不同,值域也不同。」

「正常情况下走完整混合检索加精排,分数就是 gte-rerank-v2 给出的相关性分数,大致在零到一之间。」

「精排被跳过或者调用失败时,返回的是 RRF 分数,值域能算出准确上下界。两路都排第一是 1/61 加 1/61,约等于 0.0328,这是理论最大值;只被一路召回的文档,上界是 1/61,约 0.0164;召回窗口是 150 条,最后一名下界是 1/210,约 0.0048。」

「向量生成失败时降级成纯关键词检索,返回的是 Elasticsearch 的 BM25 原始分数。这个分数没有上界,具体多大取决于查询词稀有程度和文档长度。这条路径上设了 0.3 的最低分,低于这个分的直接丢掉。」

三种排序模式及其分数含义对比图:精排、RRF与纯关键词降级

「这个字段的分数一定要和模式一起返回。0.02 这个数字,在精排模式下说明这篇文档几乎不相关,在 RRF 模式下却可能是排第一的结果。不带模式标记,谁拿到都会判断错。」

「模式分开之后,阈值才有地方可以设置,而且只能设在精排分数上。派聪明的阈值设的是 0.1,低于这个分的结果直接丢掉,不交给大模型。RRF 分数和 BM25 分数都不能套这个阈值,量纲不一样。」

「我会在出口统一换算,各自除以自己的理论上界:RRF 分除以 0.0328,精排分原样返回,同时把模式一起带出去。不用 min-max,因为 min-max 的分母是当前这批结果里的最大值,同一篇文档在不同问题下分数会不一样,跨查询没法比较,也没法拿来设固定阈值。」

「0.1 是用评测集测出来的。派聪明有一套 50 道题的评测集,每道题标了应该命中哪些文档和哪段证据,改任何检索参数都要重新测一遍。阈值原来是 0.2,分块级 Recall@5 只有 0.5652,MRR 0.4645,50 道题里有 13 道一条结果都没召回,大模型只能回答不知道。降到 0.1 之后,Recall@5 升到 0.7609,MRR 升到 0.5902,空检索降到 0,文档级召回率到了 1.0。」

「评测时发现,用户问得比较口语化时,正确分块只拿到 0.14 到 0.19 分。阈值定在 0.2,正确答案就被过滤掉了。」

「我还试过把阈值降到 0,检索指标和 0.1 完全一样。这说明 0.1 筛掉的那些结果,本来也排在前五之外,没有进最终答案。这个阈值起作用的场合,是候选本来就很少的时候。」

「如果一条结果都没有,这种情况也得有明确处理方式。系统要告诉用户没有查到相关内容,建议换个说法再问,而不是把几篇不相关文档交给大模型。因为大模型拿到不相关材料,不会说这些材料没用,它会顺着材料把话说得很圆满。这种错比直接回答不知道更难发现。」

派聪明如何写到简历上?

项目名称:派聪明(企业知识库智能问答系统)

项目简介:基于 Elasticsearch 混合检索的 RAG 问答系统,支持文档上传解析、向量化入库、权限隔离的混合检索与多轮问答,检索效果由离线评测体系保障。

技术栈:Spring Boot 3 + Elasticsearch 8 + 阿里百炼 text-embedding-v4 / gte-rerank-v2 + Kafka + Redis + MySQL + MinIO

派聪明简历技术卡片:企业知识库智能问答系统架构与检索流程

核心职责:

  • 设计混合检索方案,BM25 关键词召回与 2048 维向量 KNN 召回并行执行,召回窗口按请求 topK 的 30 倍动态计算、上限 300 条,两路结果用 RRF 融合,耗时从两路之和降为较慢一路的耗时
  • 引入 gte-rerank-v2 对融合后的前 50 条做精排,用 50 道题的评测集扫描相关性阈值,阈值从 0.2 调整到 0.1 后,分块级 Recall@5 从 0.5652 提升到 0.7609,MRR 从 0.4645 提升到 0.5902,空检索从 13 题降为 0
  • 搭建离线评测体系,覆盖 Recall@K、MRR、文档覆盖率三个检索指标,生成质量用大模型评分并抽样核对人工一致率,每次调整检索参数都重新执行并归档对比报告
  • 实现请求级超时控制,入口生成截止时间,召回、精排、生成各步取自身超时与剩余时间中较小者,剩余时间不足时跳过精排直接使用融合顺序,Embedding 失败自动降级为纯关键词检索
  • 实现三级权限过滤,用户私有、公开、组织标签三类条件在一次 Elasticsearch 查询内完成,组织标签支持层级继承,向量召回路径把权限条件放在 KNN 内部做预过滤,避免召回结果被过滤后不足

ending

由于上周只休息了一天,所以今天周二就感觉已经上了一周的班,身上的班味很重。

不论干什么都有点提不起劲。

就连 AI 圈吵得不可开交的 REA,我都懒得去关注。

希望以后不要再调休了,我滴妈呀。

今天就到这吧,能看完这篇内容的都是高手。我只能说,完事摸会鱼休息休息吧。




上一篇:程序化生成中国山水画:6000 星开源项目用 JavaScript 绘制 SVG 无限卷轴
下一篇:隐空间递归多智能体 RecursiveMAS:token 节省 75.6%、推理加速 2.4 倍
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-14 06:46 , Processed in 0.072015 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表