结合网络上面的一些内容,稍加整理 应该有一点作用 祝各位面试顺利!!!
一、流式输出
前端实现大模型流式输出,SSE与WebSocket选型逻辑是什么?各自优缺点、适用场景(结合高并发、跨端兼容)?
大模型流式输出的核心需求:服务端持续把生成的文字推给前端,客户端不需要实时发消息给服务端,这就是 SSE 的天生主场。SSE (Server-Sent Events):单向通道,服务端 → 客户端 主动推流,基于 HTTP 协议
极简实现,天然支持断线重连,兼容所有浏览器、小程序、APP、企业内网代理,服务端资源消耗少;不支持二进制数据,只能传文本,客户端不能通过 SSE 发消息,有同源连接数限制 HTTP/1.1里面一个tcp只能一条SSE
只有需要双向实时通信、强交互场景 → 用 WebSocket,比如实时语音对话、多人协作、服务端主动推送非流式消息。 WebSocket:全双工通道,客户端 ↔ 服务端 随时双向通信,独立协议
客户端可随时发消息,服务端可随时推,支持二进制:可传音频、视频、文件流,需要独立服务,百万并发下服务端压力远大于 SSE,仅做文本流输出,完全没必要用 WebSocket 部分政企网络、校园网会屏蔽
流式返回过程中网络中断、前端重连,后端如何恢复上下文继续输出?如何避免重复输出、丢包?
断点标记、断点续传、幂等去重(已存在就就掉,否则就重新渲染记录)
首先,后端在流式输出时,会为每一段内容生成唯一的递增序号 ,并将会话 ID 和每一段内容存入数据库里面,同时记录生成状态
当前端检测到断开并重连时,会携带会话 ID 和最后成功接收的递增序号给后端,后端根据会话 ID 恢复上下文,从递增序号的后面的位置继续生成内容,先补发漏的东西,然后再去推新的内容,实现断点续传
为了避免输出重复丢包,后端只返回大于前端递增序号的数据,前端进行递增序号的幂等校验,进行序号过滤,保证内容只渲染一次,按照序号拼接
用户点击“停止生成”,后端如何立即终止LLM推理、释放GPU/CPU资源?如何避免资源泄露?
前端通过发送停止指令给后端,并且携带任务id给后端
后端根据这个任务id找到对应的线程,取消上下文推理,关闭流式输出,不给llm后续token
执行toch.cuda.empty_cache(),清理GPU占用;销毁模型推理的时候创建的上下文、缓存等,GC自动回收CPU内存
设定超时终止,使用with把推理放在上下文里面,防止内存泄漏
流式返回时,如何插入非文本事件(工具调用标记、思考过程、错误提示、分段标识),且不影响前端渲染?
后端要去返回统一的json,添加type字段来区分这些非文本事件,
前端通过type去分别处理,是文本内容就直接去渲染 是调用、错误信息就执行对应逻辑,不渲染到文本里面
多轮对话+流式输出,如何保证消息不乱序、上下文不丢失?
为每一轮的对话分配id,每个流式输出的内容添加递增序号,前端按照递增序号来渲染,后端把历史消息存入数据库里面,每一轮对话都拼接历史消息给llm保证上下文不丢失,前端重连的时候给后端发送id和递增序号,后端发送大于前端递增序号的数据,同一时间只处理一个流式请求,保证不乱序
跨服务流式透传:在微服务架构之下,llm生成小段内容就通过多层服务不缓存透明的实时转发给前端。
高并发下(QPS≥1000),大量SSE长连接如何做连接复用、心跳检测、超时释放?避免OOM的核心优化点?
QPS:每秒请求数;OOM:内存溢出 SSE和webSocket都是长连接(只要建立连接之后就一直保持进行数据连接)
前端 → 网关(路由、限流、鉴权、转发) → 后端服务(业务服务、AI 推理服务、数据库) → LLM 模型
连接复用 在http/2里面实现多路复用,一个tcp可以跑多个sse ,前端可能会开很多sse 然后网关把多个sse合并管理再去发个后端,去掉多余、异常的sse (http底层是tcp)
后端定时发送检查事件,前端若长时间没有响应,判断连接失败,关闭连接
设定超时时间,如果长时间没有数据传输,连接自动释放
及时关闭失效的连接 网关层整合sse,给后端发重要的sse 限制连接的数量 使用异步非等待模型
流式输出场景中,如何实现内容安全实时截断(检测到敏感词立即停流、清理上下文)?
模型每输出一小段,然后后端就送去安全检查接口进行敏感词检查,一旦命中,根据任务id,就停止llm继续推理输出,然后返回敏感拦截事件,前端收到立即停止渲染,清空替换已经展示的违规内容,显示已经违规的提示词,关闭sse连接,停止推送, 后端清理上下文历史,避免敏感内容进入多轮对话
流式返回时,如何精准统计Token消耗(逐段统计、总消耗汇总),适配计费场景?
llm每生成一段内容就调用tokenizer来实时的计算token,并且累加事件边使用边计费
后端在返回流式json里面添加token的信息可以实时的显示给前端,实现可视化计费
在流式结束或者中断的时候,后端把最终的token消耗数量存入数据库里面,方便记账
在异常截止、敏感截断、中断的时候后端任然依照实际消耗的token来记录
使用统一的tokenizer来计算token
流式推理时,LLM模型报错(如中途断连),如何设计兜底策略,保证用户体验?
后端在流式转发过程(llm给后,后给前)之中实时监听模型状态,一但模型异常,定位到异常,触发兜底
对应网络波动等问题 后端可以设定自动重试
后端推送错误信息给前端,前端显示一些错误的提示,让用户明白发生了什么,而不是卡死白屏
对于已经生成并且前端展示的内容继续展示
支持让用户一键重试,不用再次输入新的内容
保存上下文和历史消息,重试可以基于原有的上下文推理
设定超时强制兜底,避免长期占用
跨服务流式透传时,如何做日志埋点(每段输出、耗时、异常),支撑全链路追踪?
统一追踪 ID + 分段日志 + 时序记录 + 异常捕获
当请求进入网关的时候,生成全局的统一的追踪id,在网关、业务、模型之间层层传递,全链路追踪
服务每进行一次流式转发 就异步记录一次日志包含id等 便于以后查找追溯 (上报是上报给AMP 记录时进入队列)
关键节点上报日志,发现问题,定位问题 请求进入网关,业务调用模型 流式转发 流式结束、中断
使用AMP工具可视化
二、Agent核心原理
Agent执行环路(Plan→Act→Observe→Reflect)在生产中如何落地?各环节的异常处理(如Act失败、Observe无结果)如何设计?
Plan llm根据用户的意图进行生成生成结构化计划包括步骤工具依赖等,强制输出json,限制最大步骤,把状态存入db,支持断点续跑
Act 按照计划调用工具 统一工具调用,使用支持超时鉴权限流,异步执行每一步都要记录日志和traceid
Observe 获取工具执行结果,进行清洗格式化,判断是否有效、能不能回答用户问题 结果敏感过滤、有效检测,长度截断 标准化结果给llm
Reflect llm根据结果进行判断:下一步/重试/回退重新规划/直接展示 设定最大反思次数,反思结果记录可以查看
Act 执行失败 有限次数自动重试 切换备用工具,跳过非关键继续后续计划步骤降级,无法降级直接reflect ,记录异常
Observe无结果/结果无效 工具返回问题 判断无效进入reflect调整重新执行,禁止使用无效结果生成答案
Plan 阶段异常 重新规划,任然失败返回无法处理
Reflect 死循环 限制最大循环次数,达到上限强制终止,返回已获取信息
ReAct框架在实际开发中,如何避免“思考与行动脱节”?如何优化Reason步骤的准确性?
React 思考执行观察 想一步做一步再看结果 循环结束 没有整体规划 没有反思修正 但是简单轻量好落地
强制把thought和action绑定,强制llm固定结构json输出,后端只解析这个结构,避免乱输出,把每一轮的thought action observation带入下一轮添加到上下文,让llm知道上一步干了什么,不丢历史 action合法性检测,llm输出的action不在工具表里面不合法以及校验参数,程序直接拒绝执行让llm再去reason 一次react只解决一个子问题,避免思想和行动不一致乱跳 校验工具名是否合法 校验 Action Input 是否存在 校验 Input 格式 校验参数内容
给llm工具清单和示例 限制思考范围,只使用给定的工具 观察结果结构化便于llm读懂突出关键词 加入反思
Agent工具调用的Schema设计核心是什么?如何保证LLM正确选择工具、传递正确参数(避免参数缺失、类型错误)?
schema是工具的格式规范说明书 告诉llm工具咋用 参数如何传;告诉后端校验解析执行调用
名称、描述精确,让llm可以知道什么时候使用;结构严格定义,参数类型,必要参数定义清楚;让后端可以根据schema自动校验参数,缺少直接打回 后端先把schema给llm告诉他可以使用什么工具,然后llm生成标准的工具调用json给后端,后端根据schema对json校验,合法就执行,否则就打回
工具名称直白,参数名称简单易懂,描述精确,加入示例举例什么时候使用;强制指定必填项,让llm不乱传;限制值的选填结果,避免llm乱生成;强制json输出;后端通过schema进行校验;给llm少样本示例
多步工具依赖(如“查邮件->解析内容->设定待办”),如何设计依赖管理、避免重复调用、死循环?
先进行plan对于任务进行拆解,明确依赖关系强、弱、无,进行持久化每一个步骤状态(Agent状态是全局的整个任务的大状态,小任务step的状态)之后,success才进行下一步(只有当前的step成功才可以下一步),把之前一步的结过存入上下文里,后一步直接读取;失败重试,进入反思,避免连锁错误 全部的step的状态success之后整个agent才可以completed,任何step失败,agent直接failed进入reflect
步骤幂等设计,对于重复id的任务不重复执行;对于success的状态不去重复执行;对于相同参数工具调用直接返回缓存结果
限制最大的执行步骤,超过强制终止;设置超时强制退出;调用去重,如果出现相同工具相同参数的连续调用判断循环终止(后端检测,直接去reflect);reflect不能指定重复的计划,向结束任务方向推进:提示词强制要求(告诉llm每一轮反思必须判断结果是否可以回答用户的问题),设定以获取核心信息、接近最大步骤、没有新增有效信息就强制结束(整个agent执行的环路)llm基于现有的观察结果回答问题,禁止无意义的循环
Agent的反思机制(Reflection)如何实现?如何让Agent从执行失败中学习,优化下一轮决策?
收集反思素材包括历史plan,action以及观察结果等;构造反思的prompt,让llm相结束任务的方向推进,是否可以回答用户问题,结果为什么无效,是不是工具调用的错误,结果应该重试还是重新规划;强制结构化输出,让llm必须给出可以执行的策略;根据输出进行调度,重试,换工具,重新plan或是完成
把失败原因如何改加入上下文(短期),让一下轮的llm可以看到错在哪里;把经典的错误场景加入数据库长记忆,下一次遇到问题可以直接去使用使用对于经验(查询为空→换关键词,参数问题就修改格式,网络问题进行重试);工具调用的强制约束,失败后加强工具参数的schema校验,以及缩小工具使用范围;每次失败就加深反思,开始只是反思为什么错,第二次开始规定工具使用范围,第三次直接进行重新的plan;高频错误人工审核,修正prompt
Agent的短期记忆、长期记忆如何设计存储结构?如何平衡记忆容量与查询速度?
短期记忆的定位就是本次对话的上下文记忆,会话结束或者是用完就失效。存的主要是会话历史,执行和节点的状态,可以通过有序列表、队列进行存储,结构化json存,可以存在内存里面用完自动删(会话结束,超时,超次数)
长期记忆存用户偏好,常用的参数,一些经典的场景案例,以及工具调用的一些经验。存入chroma,用于语义检索以及存入关系数据库,根据id建立索引
短期记忆利用滑动窗口,限制保留的最大轮次以及token数,只保留最近的n轮会话的历史,对于超长的结果截断
长期记忆进行向量检索、关键词过滤,做缓存层,清理无用经验
Agent调用工具超时,如何设计重试策略、熔断机制、降级方案?兜底回复如何设计才不生硬?
增加等待时间,避免持续冲击第三方服务;限制最大次数;按照错误分类为可以重试(网络)不能(参数错误);请求带上id,幂等检测,防止重复创建
熔断是防止连续的故障,引起系统崩溃。统计失败率进行熔断,一段时间停止这个工具的调用请求(直接拦截进入降级逻辑),过一段时间释放少量的请求去试试 半开重试针对的是后续的新的请求生效的
降级:返回预设信息,切换备用的一些服务,非核心直接跳过,有缓存直接使用缓存
不直接表达工具调用的错误,说当前信息查询人数较多,我暂时无法获取详细内容 人性化的自然表达
LangChain、LangGraph在生产中如何选型?LangGraph的状态机设计,如何适配复杂业务流程?
Langchain 是线性链lcel,单向的,无环 适合单向的无状态、弱状态的的流水线AI应用 rag、单轮工具调用、固定流程;Langgraph 有状态机设计,包含有向图,适合有状态,可中断回复,多步骤,多agent langgraph把langchain的链封装成节点,组成复杂工具流
设置全局的state,使用pydatic(数据校验结构化定义)来定义state的结构(schema),节点只是读取state的内容,不依赖其他的变量(不能持久储存以及不可以追踪),支持状态可序列化(转成json);节点定义每一个节点是独立的业务包括验证llm思考输入分类工具调用等等;边 包括节点直接直连的边和条件边
全局使用统一的state来管理,复杂的业务拆成小的任务节点,把节点直接使用直接边或者条件边连接
复杂场景:
多步依赖工具流:查邮件 → 解析内容 → 提取待办 → 创建日程 → 通知用户。state里面有工具调用的状态信息、任务信息、错误信息、内容信息等等,强依赖就 一步失败,后续全部不能执行;需要重试、熔断、降级
带循环反思的故障处理:用户反馈接口异常 → Agent 查日志 、查链路 → 推理原因 → 尝试修复 → 验证是否恢复 → 不行再反思重试。state里面有错误,tracedid等等;节点就包括analyze、fetchlog、reason、fix、verfiy;验证失败就回到analyze循环,超过最大步数结束
Agent执行过程如何做可观测?每一步的思考、工具调用、耗时、Token消耗、异常,如何全链路追踪?
在请求入口生成全局Traceid,请求接入,在agent调度,多轮思考、工具调用、结果返回全流程携带id;
在agent的 Plan、Act、Observe、Reflect 每个阶段都做结构化埋点(记录思考决策、LLM 调用信息、Token 消耗、工具调用参数与返回、各阶段耗时以及异常信息)
这些埋点数据通过LangSmith 提供的 SDK(专门负责上报数据工具代码) 异步上报到服务端,LangSmith 基于traceid构建执行调用树,直观展示每一步的执行顺序、token;
异常时,系统会自动捕获异常并绑定当前 TraceID,我们通过日志或告警拿到 TraceID,即可在 LangSmith 中定位完整执行过程,快速排查问题。
多个用户同时触发同一个Agent任务,如何做幂等设计,避免重复执行(如重复查询数据库、调用接口)?
同一个任务、同一个唯一标识,无论执行多少次,最终只执行一次。
设定全局唯一的幂等标识,用户id+任务id+参数构成幂等键
进入前查看状态机(pending /running/success /failed),任务完成就直接输出
未执行用分布式锁(同一时间,只放一个请求进去执行)来保证同一时间只有一个请求
执行过程、结束更改任务状态
在agent的工具调用等都做幂等设计
Agent如何安全传递用户身份(登录态、权限),调用工具时避免身份泄露、越权?
网关统一鉴权 + 安全上下文隔离 + 工具层权限校验
首先在入口服务完成用户登录态验证,解析出用户 ID、权限集合,构造不包含敏感凭证的轻量化身份上下文,不直接传递原始 Token 或密码,不给prompt,系统保存,只是去确认工具调用的身份 在任务执行结束销毁
在 Agent 工具执行前会强制进行权限校验,确保用户只能访问自身权限范围内的数据与接口
同时对敏感操作做二次确认,对返回结果做脱敏处理,使用短期令牌降低泄露风险,从传输、模型、工具、数据四层保证身份安全与防越权
认证=你是谁?登录、token 验证;鉴权=你能干什么?
前端->网关->API 服务层->Agent ->工具执行层->数据层 / 外部服务层
如何实现Agent执行过程的可回放、可打断、可人工干预?
用 TraceID 串联一次完整执行流程 ,对每一步执行做快照记录,包括思考、LLM 调用、工具调用与状态,实现按链路可回放。
在agent的执行流程 plan act observe reflect 设定中断检查,当中断的时候(前端取消,超时,异常)及时停止llm推理,工具调用,记录中断的状态,释放资源
最后在高危或关键步骤(删除数据、资金与交易类、覆盖写入、发短信、推送通知)设置人工断点,让 Agent 主动暂停,支持人工修正参数、补充信息或确认操作,确认后从断点继续执行,形成完整的人机协同闭环。
Agent的任务分解能力如何优化?如何让Agent正确拆分复杂任务?
让 Agent 学会结构化拆解、减少歧义、避免遗漏、保证可执行
在prompt之中明确要求去把大任务拆解为子任务,一个子任务只做一件事,步骤清晰可执行,有依赖:明确先后顺序,每个步骤有明确完成标准,添加几个实例Few-shot;
强制结构化输出JSON ,任务列表、依赖、输入输出、预计工具等参数
加入反思,自我校验拆解是否合理 子任务是否覆盖原始需求 拆解 → 校验 → 修正 → 再拆解闭环
引入外部能力增强拆解 使用专用分解模型来规划 历史上正确的任务拆解存入向量库,相似任务直接参考模板,保证一致性
Agent与现有后端系统对接,如何保证接口调用的稳定性、一致性?
标准化接口 + 幂等 + 限流熔断 + 异步解耦 + 状态校验 + 异常兜底。
统一请求 / 响应格式,让 Agent 能稳定理解与调用
接口全部实现幂等,通过请求 ID 与状态机保证重复调用不会产生脏数据(错误、冗余、不一致的数据)
增加限流、熔断、超时控制,保护 FastAPI 不被突发流量打垮
耗时异步解耦(任务提交和结果等待分开),避免 Agent 阻塞超时,高危接口人工确认,
身份与权限由系统托管注入,FastAPI 统一做鉴权,不依赖 Agent 传参
统一异常处理与清晰错误提示,让 Agent 可自动重试、可自我修正
如何评估Agent的任务完成率?生产中如何统计Agent的成功率、错误率、步骤合理性?
评估 Agent 效果主要从任务完成率、成功率错误率、步骤合理性三个维度展开
任务完成率通过目标验收机制判断,用规则或评估模型校验是否达成用户真实需求
通过全链路埋点和 TraceID 做结构化统计,从任务和步骤两个维度计算成功率、错误率、异常分布
步骤合理性则通过分析平均步骤数 无效步骤占比 工具调用重复率来评估评估 Agent 是否高效、无冗余地执行任务。
三、RAG生产落地痛点题
百万级文档RAG,检索延迟要求<200ms,如何设计索引、分片、缓存架构?
采用向量索引(语义)+ BM25 关键词索引 + 元数据索引(剪枝)的混合索引结构。向量侧(文本转成向量)使用 HNSW (HNSW 是一种基于图的向量索引)索引,兼顾召回精度与检索速度;BM25 实现关键词快速匹配;同时对来源、文档类型、时间等建立元数据索引,实现先过滤、后检索,大幅减少实际参与匹配的数据量。
按元数据分片,例如按部门、文档类别或时间范围等分片,让单次查询只访问目标分片,避免全库扫描。每一个分片独立维护一套自己的向量索引 + BM25 倒排索引;查询时对多路检索并行执行 每个分片包括两个索引+文档块
缓存 = 内存 采用多级缓存降低时延:L1 本地内存缓存热点 Query 与TopK 召回结果;L2 Redis(独立的内存缓存服务,放在内存里的、专门用来做缓存的数据库) 缓存高频查询向量与 TopK 召回结果
每个分片进行分片级缓存,存高频查询向量、向量检索、bm25检索结果,在多路召回的时候读自身的内存缓存
文档频繁更新/删除,向量库如何保证实时一致性?如何避免召回旧知识、脏数据?
增量更新 + 版本控制 + 准实时刷新 + 脏数据过滤机制
文档更新 / 删除时,不直接删除原始向量,而是标记为已删除 / 已过期,并新增新版本向量,检索时自动过滤掉标记失效的向量,从根源避免召回脏数据
每个文档块对应唯一版本号,向量库中存储文档 ID + 版本号。查询时带上版本过滤条件,只召回最新版本的向量,杜绝旧数据。
文档更新立即写入向量数据库
在元数据里面添加更新时间,检索之前根据时间进行过滤
文档更新之后删除l1、l2的缓存
L1是本地内存不用走网络,微秒级,快到极致;L2要走网络请求,毫秒级
超高频率的查询直接在本地秒回,L2 是分布式 Redis 缓存,多实例共享,提升整体缓存命中率
同一用户同一问题多次查询,如何做检索结果缓存?如何处理“缓存过期”与“新知识更新”的矛盾?
用户id和问题内容哈希绑定,便于同一用户同一问题可以直接找到;把热点问题和召回结果缓存到本地内存以及redis里面,先来在本地内存里面找,未命中再去redis里面找,都没有再去实际检索召回
设定合理的失效清理时间,既可以减少检索次数,也可以避免缓存不更新;一但更新就立即删掉缓存内容,重新进行缓存;在缓存快要失效的时候,异步更新,不阻塞
用户问题模糊,如何做意图识别+查询改写+多路召回,提升召回率?
意图识别 → 查询改写 → 多路召回
先通过llm对问题进行意图分类,识别关键词、时间、约束条件,判断是什么问题(事实查询、对比类、闲聊 )
对于简短的问题扩写增强,生成多个角度的语句(换说法)
利用向量检索和bm25检索进行多路召回,既保证语义,又保证关键词
利用大模型对原问题生成多个语义一致、表述不同的查询句子,把模糊、简短的问题扩写成更丰富、更容易匹配知识库的形式,同时加上缓存,避免重复调用大模型,保证检索速度。
表格、带格式PDF、图片文本的RAG,如何处理才能不丢失结构信息(如表格行列关系、PDF排版)?
行列遍历表格内容,保留对应的行列关系;使用fitz来解析pdf,标题层级、段落顺序、排版位置还原文本结构; 图片进行ocr识别文字,然后LayoutLM看位置、看格式、看结构进行版面分析
长文档(10w字+)RAG出现“中间内容丢失”,如何用父子分块、分层检索、重排序解决?
10w 字切成了很多小 chunk,检索的时候得到的是前面一块以及后面一块,中间有一块丢了
先把长文档切成大的父块(整段、整章节,保留完整上下文),再把父块切成小的子块(用于向量检索),检索时先命中子块,在找到对应的父块;
第一层:对章节标题、大纲、摘要做粗粒度检索,快速定位到父块;第二层:在命中的章节内部做细粒度向量检索,精准定位到子块;两层结合,既不遗漏大范围上下文,又能保证精准度,避免中间段落丢失。
先用多路召回拉回足够多的候选片段,扩大覆盖范围;再通过重排序模型对片段相关性打分排序,把分散在文档各处、但语义相关的中间内容排到前面;最后拼接 Top-K 结果,保证上下文连贯、不丢失关键中间信息。
混合检索(稀疏+稠密)在生产中如何调参?如何平衡召回率与检索速度?
向量检索 bm25关键词检索
召回数量调参 稠密检索(把文本转为稠密向量)先设置topk为10~20,保证语义精准,然后稀疏检索设定为5~10条,补充强关键词强匹配,总候选控制在15~30条,避免后续重排压力太大
权重融合调参 在注重专业词场景/法规 提高bm25关键词的检索权重,在模糊、偏口语的场景提高向量检索
给两个检索设定相似度阈值和得分阈值,减少无效候选,设定融合之后的最大召回数量,进行截断
检索阶段适当扩大召回条数,保证高召回率(真实相关的文档中,被成功检索出来的比例);用 Rerank 做精排,只保留最相关的少量片段进入大模型。
先过滤元数据(日期、部门、文档类型),缩小检索范围;再做稀疏 + 稠密混合检索,减少向量库计算量。
向量库使用HNSW 索引提高检索速度
RAG与多轮对话结合,如何实现“基于历史上下文的自动检索”?避免重复检索、无效检索?
基于对话上下文 改写 + 压缩 + 过滤,实现自动关联检索
根据上下文来对本轮的对话(可能省略主体、限定词)进行补全,形成完整的问句,判断问题的类型以及约束条件,查看历史有没有缓存相似的检索,实现复用,检索之前进行约束过滤,减少开销
进行问题的意图分析,判断问题的类型,利用缓存进行复用
如何避免RAG检索到大量无关片段,导致LLM回答跑偏?(落地优化手段)
使用向量检索和bm25关键词检索进行多路召回,设定相似度和得分阈值,进行截断,然后进行rerank重排,筛选高度相关的内容
利用元数据进行前置过滤,再去检索
合理进行分块,保证片段的语义完整
进行意图分析,明确问题类型,约束等
在prompt里面强制约束 仅根据检索到有效的内容进行作答,禁止乱编造
生产环境如何自动化评估RAG效果?
离线批量测评 + 线上抽样监控 利用RAGAS 体系 + 传统检索指标
利用检索的阈值,重排的质量来衡量召回率、精确度(reranker越准,无用语句越少,结果越精确)
基于ragas框架进行自动打分,计算:事实一致性、回答正确率、上下文召回率、上下文精确率 来评价模型的回答
构建不同场景的测试样本,版本迭代(改动分块、检索、重排等)之后跑一边,来指出波动
线上对用户的请求(问题、上下文、检索结果、rerank结果、llm结果)随机抽样,对于结果进行ragas打分监测
Embedding模型如何选型?中英文文档混合场景,如何选择合适的Embedding模型,平衡效果与速度?
双语能力、向量维度(纬度越高语义越细、检索越准 → 存储 / 计算越慢)、最大文本长度、推理速度、参数量
模型选择 长度控制 检索重排链路搭配 向量检索利用embedding模型 关键词靠词频统计利用算法
向量检索中,余弦相似度、点积、欧氏距离的实际应用差异?如何选择?
余弦相似度 看向量的夹角,忽略长度 ,不受向量长度影响,只比语义 ,RAG 语义检索 Embedding 匹配,
点积 对于位置乘积求和,涉及相邻的方向和长度,适用于未归一化向量(方向相似性、可能模长代表了图像的清晰度文本的语义丰富度,点积比余弦更符合,而且省去了归一化)、大模型打分(既能判断语义相似度,又能体现模型置信强弱),推荐系统(用户向量和物品向量匹配度,用户模长代表兴趣度,物品表示受欢迎程度)
欧式距离 计算空间距离的绝对值 受向量的模长影响 值越小越相似 适合聚类,不用于文本rag
RAG的rerank重排环节,如何选择重排模型?如何优化重排速度?
语言适配 精度要求匹配量级 根据上下文长度来选
控制多路召回的候选者数量;使用gpu加速,本地部署,减少网络耗时;先使用小模型粗筛(快速砍掉无关片段),设定ranker的阈值,截断保留,再利用大模型对保留的候选者进行重排
动态知识更新场景(如每日新增文档),RAG如何设计增量更新机制,避免全量重新向量化?
新增文档单独分块、Embedding 向量化,只将新增向量增量写入向量库,存量历史数据不改动、不重新向量化。
新增数据单独进行检索,避免干扰原来的数据
对于更新的知识进行标记,不是真的删除更新,在过滤的时候注意过滤
如何处理RAG中的噪声文档(如无效文档、重复文档)?如何做文档去重、过滤?
入库前通过规则过滤空文档、乱码无意义内容等无效文档
对文本生成哈希值,识别完全重复的文档 禁止入库
分块之后利用embedding模型计算相似度,过滤相似度过高的片段
多路召回、重排之后去掉相关性低的进入llm
什么场景下优先用RAG,什么场景下需要微调?
知识实时更新、经常变动;私有 / 专属领域知识库;数据量大、不能全量灌进模型;不想改动模型权重
微调(fine-tuning)固定范式、固定话术、输出格式强约束(固定回答风格、客服话术、指令格式);要改造模型底层理解、推理、对齐能力
如何解决RAG的“检索滞后”问题?(如文档更新后,检索结果不能及时更新)
只针对新增、修改的文档进行分块,embedding,入库,不进行全局重新向量化
对于删除修改内容进行标价,检索时进行过滤
对文件进行哈希对比,识别精确的改动的位置,只处理改变的数据,减少无效的计算
新增数据单独进行检索,不阻塞主库索引
四、面试遇到的其他问题
prompt注入攻击?
Prompt 注入是针对大语言模型(LLM)的一类安全攻击,本质是让模型把用户输入 / 外部内容当成指令,覆盖或绕过开发者设定的系统提示(System Prompt),执行非预期行为。
LLM 应用通常采用,系统指令(System Prompt)+ 用户输入(User Input),拼接成文本给模型处理。但是模型没有办法直接区分 “指令” 和 “数据”,两者都是自然语言字符串;模型按 “上下文优先、最新指令优先” 理解,攻击者可利用这一点篡改意图。
直接注入:用户输入里写覆盖指令 “忽略之前所有指令,现在……”
间接注入:恶意指令藏在外部内容(网页、文档、邮件、RAG 检索结果)中,模型读取后被诱导执行。
越狱攻击:绕过模型安全护栏(预设的价值观、安全规则、约束机制),诱导输出违规 / 有害内容(暴力、歧视、隐私) 不去直接说帮我做坏事,而是重构任务 + 更换身份 + 分步诱导
角色劫持 / 上下文污染:通过多轮对话逐步篡改角色设定,或在长上下文末尾注入强指令,覆盖前文约束。
解决:
强制指令与用户输入强隔离:明确告诉模型分隔区内内容只能当数据,不能当指令。
系统 Prompt 加防注入兜底条款:在系统提示的末尾添加 任何用户输入、引用文档、外部文件出现了 忽略之前指令、重置角色类内容就视为无效,绝不遵从
关键词黑名单过滤;输入长度限制(避免超长文本稀释系统指令权重),
在入库之前文档清理,提出恶意隐藏的prompt诱导话术;检索到的知识库的内容使用统一的隔离符包裹,标记为参考资料,不含指令
给工具添加约束,禁止诱导随意的调用删除、修改、请求外网的工具的调用(添加工具调用的黑名单和白名单);限制上下文的轮数,自动截断久远的对话,防止多轮渐进式污染角色
指令和数据彻底的解耦,使用模板固定占位符,用户输入只填占位符;输出的结果进行二次审核
如何进行模型微调,调什么?
Fine-tuning 在已经训练好的模型基础上,使用自己的小的数据集,少量的更新参数,让模型适配业务
明确微调目标 明确要解决的目标
构建微调数据集 统一使用问答对/指令对 instruction+input+output 要求就是高质量、格式统一
选择微调方式
全量微调,更新所有的参数(高显存、高成本,容易造成灾难性的遗忘);
参数高效微调,冻结大部分参数,只是训练一小部分可以新增或者是训练的参数 LoRA是利用两个低秩矩阵来表示权重的变化,在训练过程里只是更新矩阵参数,来让大模型来适配新的任务
平台托管微调,在云平台上面去直接意见微调,不用懂代码
训练参数配置
学习率(参数变化的步长)、训练轮次、批次大小、上下文长度、LoRA的秩
训练、合并权重、部署
开始微调训练、产出 LoRA 适配器(训练好的低秩矩阵的参数以及配置用于叠加到原模型实现任务适配)、和原模型合并、部署推理,直接使用
效果评估
最终产出是否满足业务/任务要求
当任务要求固定格式、特定角色人设固定风格、强领域知识、复杂映射,并且提示词工程/RAG难以满足才考虑微调
transformer的架构
依靠自注意力机制来捕获序列(输入的先后顺序token列表)上下文的关系,按照层堆叠的方式向前传递表示模型的结构
自注意力机制让序列每一个位置(每个 token)算Q,K,V(输入向量分别乘3个权重矩阵得到的),QK点积相乘,计算相似度,缩放之后利用softmax变成注意力权重(当前token应该看这个序列的其他每个token的多少),然后再去对V加权求和得到融合上下文的新的token。
Encoder将输入的序列转为嵌入加位置编码之后,通过多层的encoderlayer(每层有自注意力和前馈网络)得到编码表示给Decoder使用,依次通过多层的decoderlayer(每一层有掩码自注意力、交叉自注意力和前馈神经网络)解码,最终得到预测序列。
FNN的作用是把自注意力得到的新的融合上下文的新的token做非线性变化增强表达能力
掩码自注意力 当前位置不能看到后面的token,基于已生成部分不偷看未来 防止作弊
交叉自注意力 KV来自于encoder输出固定的,然后Q是新计算的 用于decoder去查询encoder 生成目标序列要依赖原序列