AI-Interview
[!Interview]
- 项目架构怎么设计?
- Agent 系统怎么拆分?
- Planner/Tool/Memory 怎么分层?
- Memory 怎么搞?短期、长期和用户画像各自怎么处理?
- 延迟、成本、效果如何平衡?Token 成本、推理延迟、RAG 召回策略怎么权衡?
- RAG 效果怎么评估?召回率、准确率,线上怎么验证?
高频:
- Tool Calling
- Memory
- RAG
Learning
Agent & 系统架构
-
- 什么是 AI Agent?
-
- Agent 和普通 ChatBot 有什么区别?
-
- 如何实现多 Agent 协作系统?
-
- 什么是 ReAct Agent?
-
- AI Chat 系统的整体架构是什么?
-
- 如何设计一个 AI 问答系统架构?
-
- Agent 如何做任务规划(planning)?
-
- Agent workflow 和普通 workflow 有什么区别?
-
- Agent 为什么需要 memory?
-
- Agent 如何避免无限循环调用工具?
RAG
-
- 什么是 RAG(Retrieval Augmented Generation)?
-
- RAG 主要解决什么问题?
-
- RAG pipeline 的完整流程是什么?
-
- RAG 系统主要组件有哪些?
-
- chunk size 为什么很重要?如何选择?
-
- 文档切分有哪些策略?
-
- RAG 如何做 rerank?
-
- 如何实现 hybrid search(向量 + keyword)?
-
- RAG latency 怎么优化?
-
- 如何评估 RAG 系统效果?
-
- RAG 如何避免检索错误?
Memory
-
- 什么是 ChatMemory?
-
- Agent memory 有哪些类型?
-
- 如何实现对话历史 memory?
-
- 大模型上下文窗口是什么?如何突破长度限制?
Embedding & 向量数据库
-
- embedding 和向量相似度搜索是什么?
-
- embedding 模型如何选择?
-
- embedding 模型如何影响检索效果?
-
- 向量数据库为什么适合语义检索?
-
- 向量数据库如何进行相似度计算?
LLM 原理
-
- 什么是大语言模型(LLM)?
-
- Transformer 架构核心原理是什么?
-
- Self-Attention 的计算流程是什么?
-
- 什么是 hallucination(幻觉)?为什么会发生?
-
- 如何减少大模型 hallucination?
-
- LLM 为什么推理成本高?
-
- Temperature、Top-p、Top-k 有什么区别?
Tool Calling & Prompt
-
- 什么是 Tool Calling?
-
- 什么是 Prompt Engineering?
-
- ChatGPT 的 system / user / assistant role 有什么作用?
-
- LangChain4j 如何实现 Tool 调用?
-
- LangChain4j 如何返回结构化 JSON?
-
- LangChain4j 如何实现 prompt template?
-
- 如何设计 Prompt 管理系统?
-
- 如何评估 Agent 的执行效果?
Java / Spring AI / LangChain4j
-
- 什么是 AI Service(LangChain4j)?
-
- Spring AI 和 LangChain4j 有什么区别?
-
- LangChain4j 和 Python LangChain 有什么区别?
-
- 如何在 Spring Boot 中集成 LangChain4j?
-
- Java 如何实现 streaming response?
-
- Java 调用 OpenAI API 如何设计 SDK?
-
- Java LLM 服务如何做连接池管理?
工程化 & 可观测性
-
- 如何实现 SSE 推送?
-
- streaming response 如何实现?
-
- LLM 服务如何做缓存?
-
- LLM 服务如何做限流?
-
- LLM 服务如何做降级?
-
- 如何做模型 fallback?
-
- 多模型调度如何实现?
-
- LLM 如何实现多租户?
-
- LLM API 如何设计接口?
-
- LLM latency 如何优化?
-
- MCP(Model Context Protocol)是什么?
-
- AI系统如何记录 Prompt 和 Response?
-
- AI系统如何做监控?
-
- AI系统如何做成本控制?
-
- AI系统如何做权限控制?
-
- 如何统计 token usage?
-
- 如何设计 AI evaluation pipeline?
-
- 如何做 A/B test 比较不同模型?
参考答案
Agent & 系统架构
1. 什么是 AI Agent?
AI Agent 是一个能够感知环境、自主规划、调用工具并执行任务的智能系统。与普通 LLM 一问一答不同,Agent 具备以下能力:
- 感知:接收用户输入、工具返回结果、上下文状态
- 规划(Planning):利用 LLM 进行推理、任务分解、多步决策
- 执行(Action):调用外部工具(搜索、数据库、API、代码执行等)
- 记忆(Memory):维护短期对话上下文和长期知识状态
- 反馈循环:根据工具执行结果调整下一步行动
典型框架:LangChain4j AiServices、Spring AI、AutoGen。
2. Agent 和普通 ChatBot 有什么区别?
| 维度 | ChatBot | Agent |
|---|---|---|
| 能力 | 仅文本生成、对话 | 调用工具、执行动作、操作外部系统 |
| 规划能力 | 无 | 任务分解、多步推理、ReAct 循环 |
| 记忆 | 短期上下文窗口 | 短期 + 长期 + 外部状态 |
| 自主性 | 低,依赖用户引导 | 高,可自主决策下一步 |
| 适用场景 | 客服、FAQ、闲聊 | 复杂任务自动化、代码生成执行、数据分析 |
3. 如何实现多 Agent 协作系统?
多 Agent 系统常见模式:
- Orchestrator-Worker 模式:一个主 Agent 负责任务拆解和调度,多个子 Agent 各司其职(搜索 Agent、代码 Agent、数据库 Agent)
- Pipeline 模式:各 Agent 串行处理,前一个输出作为后一个输入
- 竞争/投票模式:多个 Agent 独立执行,取最优或投票决策
- 消息总线模式:Agent 通过消息队列(如 Redis Pub/Sub)异步通信
关键要素:
- 清晰的 Agent 角色定义和能力边界
- 统一的消息格式(通常是结构化 JSON)
- 任务状态追踪(防止死循环)
- 错误处理和超时机制
LangChain4j 可通过 AiServices 组合多个 service 实现,Spring AI 通过 Tool 注入实现子任务委派。
4. 什么是 ReAct Agent?
ReAct = Reasoning + Acting,是一种将推理和行动交替进行的 Agent 模式:
1 | Thought: 我需要查询用户的订单信息 |
优点:推理链路透明可解释,工具调用有明确依据。
在 LangChain4j 中通过 @Tool 注解 + AiServices 自动实现 ReAct 循环。
5. AI Chat 系统的整体架构是什么?
1 | 用户请求 |
辅助组件:向量数据库(Milvus/Weaviate)、关系数据库(MySQL 存会话)、监控(Prometheus + Grafana)、日志(ELK)。
6. 如何设计一个 AI 问答系统架构?
核心链路:用户问题 → Query 改写 → RAG 检索 → Prompt 构建 → LLM 推理 → 答案后处理 → 返回
关键设计点:
- Query 改写:多路查询扩展(HyDE)、意图识别
- 检索层:向量检索 + BM25 混合检索,rerank 精排
- Prompt 构建:System prompt + 检索上下文 + 对话历史 + 用户问题
- 答案验证:Faithfulness 检查(答案是否基于检索内容)
- 缓存:语义缓存相似问题
- 降级:RAG 无结果时 fallback 到纯 LLM 回答
7. Agent 如何做任务规划(planning)?
主要规划策略:
- ReAct:边推理边执行,逐步决策
- Plan-and-Execute:先生成完整执行计划,再逐步执行(适合确定性强的任务)
- Tree of Thought(ToT):树状探索多条路径,选最优路径
- Self-Consistency:多次采样取一致性最高的答案
在 LangChain4j 中可用 AiServices + 多步对话实现,或集成 LangGraph4j(Graph 状态机)做复杂规划。
8. Agent workflow 和普通 workflow 有什么区别?
| 维度 | 普通 workflow | Agent workflow |
|---|---|---|
| 决策方式 | 预定义流程,硬编码条件 | LLM 动态决策,灵活路由 |
| 适应性 | 低,新情况需修改代码 | 高,LLM 可处理未见情况 |
| 可解释性 | 高 | 相对低(黑盒推理) |
| 稳定性 | 高 | 较低(非确定性) |
| 适用场景 | 固定流程审批、ETL | 复杂对话、开放式任务 |
Agent workflow 通常通过状态机(如 LangGraph)管理节点流转,结合 LLM 做路由判断。
9. Agent 为什么需要 memory?
LLM 本身是无状态的,每次请求独立。Agent 需要 memory 的原因:
- 上下文连贯性:多轮对话需要记住前几轮的内容
- 任务状态追踪:多步任务中记录已完成哪些步骤
- 用户偏好:长期记住用户习惯、个性化设置
- 工具调用结果:保存中间工具执行结果供后续步骤使用
没有 memory,Agent 每次都从零开始,无法完成需要上下文的复杂任务。
10. Agent 如何避免无限循环调用工具?
- 最大迭代次数限制:设置
maxIterations(如 LangChain4j 默认10次),超过则强制终止 - 循环检测:检测连续相同 Action + 相同参数,判定为循环,中断执行
- Token/时间预算:设置最大 Token 消耗或超时时间
- 工具幂等性标记:对已执行过的工具+参数组合做去重
- 强制终止条件:在 System Prompt 中明确说明”若无法得出结论,直接回复无法完成”
RAG
11. 什么是 RAG(Retrieval Augmented Generation)?
RAG = 检索增强生成,是将外部知识检索与 LLM 生成结合的技术:
- 用户提问 → 向量化 query
- 在向量数据库中检索相关文档片段
- 将检索结果拼入 Prompt
- LLM 基于上下文生成答案
解决了 LLM 知识过时、幻觉、私有知识无法使用等问题。
12. RAG 主要解决什么问题?
- 知识时效性:LLM 训练数据有截止日期,RAG 可接入实时/私有知识库
- 幻觉(Hallucination):提供真实文档作为依据,减少 LLM 凭空捏造
- 私有数据:企业内部文档、代码库不可能放入训练数据,RAG 可低成本接入
- 可溯源性:答案来自检索文档,可提供引用来源
13. RAG pipeline 的完整流程是什么?
离线阶段(Indexing):
1 | 原始文档 → 文档解析 → 文本切分(Chunking)→ Embedding → 存入向量数据库 |
在线阶段(Retrieval & Generation):
1 | 用户 Query → Query 预处理/改写 → Embedding → 向量检索(Top-K) |
14. RAG 系统主要组件有哪些?
| 组件 | 作用 | 常用工具 |
|---|---|---|
| 文档解析 | PDF/Word/HTML 转文本 | Apache Tika, PDFBox |
| 文本切分 | 按语义/固定大小切块 | LangChain4j TextSplitter |
| Embedding 模型 | 文本向量化 | OpenAI Ada, BGE, M3E |
| 向量数据库 | 存储和检索向量 | Milvus, Weaviate, Qdrant |
| Reranker | 精排检索结果 | Cohere Rerank, BGE-Reranker |
| LLM | 基于上下文生成答案 | GPT-4, Claude, Qwen |
| 缓存层 | 相似问题缓存 | Redis + 语义相似度 |
15. chunk size 为什么很重要?如何选择?
chunk size 影响检索精度和上下文完整性:
- 太小(< 128 tokens):语义不完整,检索准确但缺乏上下文,答案不完整
- 太大(> 1024 tokens):噪音多,相关性被稀释,检索质量下降
- 推荐策略:
- 通用文档:256-512 tokens,overlap 50-100 tokens
- FAQ/问答对:一问一答为一个 chunk
- 代码:按函数/类切分
- 长文档:先按段落/标题切分,再细分
建议通过评估(召回率 + 答案质量)来确定最佳 chunk size。
16. 文档切分有哪些策略?
- 固定长度切分:按 token 数量固定切分,简单但可能截断语义
- 递归字符切分(RecursiveCharacter):优先按段落→句子→词切分,LangChain4j 推荐
- 语义切分(Semantic):通过 embedding 相似度检测语义边界,质量最高但最慢
- 句子切分:按句号/换行切分,适合新闻、评论类文本
- 结构化切分:按 Markdown 标题、HTML 标签、代码块边界切分
- 父子切分(Parent-Child):存储大 chunk,检索小 chunk,返回时扩展为父 chunk
17. RAG 如何做 rerank?
Rerank 是对向量检索 Top-K 结果进行二次精排,提升相关性:
方式一:Cross-Encoder Reranker(质量最好)
1 | 每个 (query, chunk) 对送入 rerank 模型,输出相关性分数 |
方式二:LLM Rerank
1 | 让 LLM 对检索结果排序(成本高,速度慢) |
方式三:RRF(Reciprocal Rank Fusion)
1 | 合并多路检索结果的排名,公式:score = Σ 1/(k + rank_i) |
LangChain4j 中通过 ContentAggregator + ReRankingContentInjector 实现。
18. 如何实现 hybrid search(向量 + keyword)?
Hybrid Search = 向量语义检索 + BM25/全文关键词检索,互补优势:
1 | // 向量检索 - 语义相似 |
支持 hybrid search 的向量数据库:Weaviate、Qdrant(native hybrid)、Elasticsearch(dense_vector + BM25)。
19. RAG latency 怎么优化?
| 优化点 | 方法 |
|---|---|
| 向量检索 | ANN 近似检索(HNSW)替代精确检索,topK 控制在 5-10 |
| Embedding | 本地部署小模型,或 batch 请求 |
| Rerank | 只对 Top-K 做 rerank,减少候选数量 |
| 缓存 | 语义缓存(相似问题直接返回缓存答案) |
| 并行化 | 多路检索并行,embedding + 检索 pipeline 化 |
| Prompt 压缩 | 对检索内容做摘要压缩,减少 LLM 输入 |
| 流式返回 | SSE/Streaming 让用户先看到部分答案 |
20. 如何评估 RAG 系统效果?
检索评估:
- Recall@K:相关文档在 Top-K 中的召回比例
- MRR(Mean Reciprocal Rank):最相关文档排名的倒数均值
- NDCG:归一化折扣累计增益
生成评估:
- Faithfulness(忠实度):答案是否有检索内容支撑(防幻觉)
- Answer Relevance:答案是否回答了用户问题
- Context Precision/Recall:检索上下文是否恰当
工具: RAGAS 框架(自动化评估)、人工标注金标集对比。
21. RAG 如何避免检索错误?
- Query 改写/扩展:HyDE(生成假设文档再检索)、多 Query 扩展增加召回
- 提高 Chunk 质量:合理切分、去重、清洗噪音数据
- Hybrid Search:向量 + 关键词双路检索,避免单一召回失败
- Rerank:精排过滤低相关结果
- No-answer 判断:检索结果相似度低于阈值时,直接回复”知识库无相关信息”而非强行生成
- Faithfulness 检查:生成答案后验证是否有对应原文依据
Memory
22. 什么是 ChatMemory?
ChatMemory 是维护对话历史的组件,让 LLM 在多轮对话中保持上下文。
LangChain4j 提供两种实现:
- MessageWindowChatMemory:保留最近 N 条消息(滑动窗口),超出则截断最旧消息
- TokenWindowChatMemory:按 Token 数量限制,超出则从最旧消息开始删除
1 | ChatMemory memory = MessageWindowChatMemory.withMaxMessages(20); |
多用户场景需为每个 userId 维护独立的 ChatMemory 实例(通常存 Redis/DB)。
23. Agent memory 有哪些类型?
| 类型 | 描述 | 存储方式 |
|---|---|---|
| 短期记忆(Working Memory) | 当前对话上下文,Token 窗口内 | 内存/Context Window |
| 长期记忆(Long-term Memory) | 跨会话持久化信息,用户历史偏好 | 数据库 / 向量库 |
| 情节记忆(Episodic Memory) | 历史对话的摘要/关键事件 | 向量数据库(可语义检索) |
| 语义记忆(Semantic Memory) | 结构化知识、用户画像、事实 | KV 存储 / 图数据库 |
| 程序记忆(Procedural Memory) | Agent 如何使用工具的策略 | 内嵌于 System Prompt |
24. 如何实现对话历史 memory?
1 | // LangChain4j 实现多用户对话 Memory |
25. 大模型上下文窗口是什么?如何突破长度限制?
上下文窗口:LLM 单次推理能处理的最大 Token 数(如 GPT-4 128K、Claude 200K)。
突破长度限制的方法:
- 滑动窗口:保留最近 N 轮对话,丢弃最旧
- 对话摘要压缩(Summary Memory):定期将旧对话总结为摘要,只保留摘要
- RAG 化 Memory:将历史存入向量库,按需检索相关片段注入上下文
- 分层 Memory:近期对话保留原文,远期对话保留摘要
- 文档分块处理:长文档切分多次处理,用 Map-Reduce 模式合并结果
Embedding & 向量数据库
26. embedding 和向量相似度搜索是什么?
Embedding:将文本(或图片)映射为一个高维实数向量,语义相近的文本在向量空间中距离较近。
1 | "苹果手机" → [0.23, -0.15, 0.87, ...] (1536维) |
向量相似度搜索:在海量向量中找出与 query 向量最相近的 Top-K 向量,常用算法:
- 余弦相似度(Cosine Similarity):最常用,衡量方向夹角
- 内积(Dot Product):效率更高,适合归一化向量
- 欧氏距离(L2):衡量绝对距离
27. embedding 模型如何选择?
| 维度 | 选择建议 |
|---|---|
| 语言 | 中文优先:BGE(BAAI)、M3E、text2vec;多语言:multilingual-e5 |
| 精度 vs 速度 | 高精度:bge-large;高速度:bge-small、bce-embedding-base |
| 向量维度 | OpenAI Ada: 1536维;BGE-large: 1024维;BGE-small: 512维 |
| 私有化部署 | 优先 BGE 系列(开源),可本地部署 |
| 通用场景 | OpenAI text-embedding-3-large 效果最好但有成本 |
评估方法:在业务数据上跑 MTEB 基准或自定义检索评估集。
28. embedding 模型如何影响检索效果?
- 语义理解能力:好的 embedding 模型能理解近义词、上下位关系,差的模型只能匹配字面
- 领域适配:通用 embedding 在垂直领域(医疗/法律/代码)效果差,需领域微调
- 语言适配:中文 embedding 用中文训练的模型,避免用英文模型强行处理中文
- 向量维度:维度越高表达能力越强,但检索速度越慢(存储和计算开销↑)
- 相似度函数匹配:不同模型可能优化不同的相似度函数(Cosine vs Dot Product),需配套使用
29. 向量数据库为什么适合语义检索?
传统数据库(MySQL)是精确匹配(WHERE name = ‘xxx’),无法做语义相似搜索。向量数据库的优势:
- ANN(近似最近邻)算法:HNSW、IVF 等索引支持毫秒级亿级向量检索
- 语义相似度:基于 embedding 的距离,捕捉语义而非字面匹配
- 过滤能力:支持 metadata 过滤(如只检索某部门的文档)
- 可扩展性:Milvus、Qdrant 支持分布式水平扩展
常用向量数据库:Milvus(大规模)、Qdrant(轻量高性能)、Weaviate(自带 embedding)、pgvector(PostgreSQL 插件,适合小规模)。
30. 向量数据库如何进行相似度计算?
精确计算(Exact Search): 暴力遍历所有向量,计算余弦相似度,准确但 O(n) 慢。
近似最近邻(ANN):
- HNSW(Hierarchical Navigable Small World):图索引,查询速度极快(微秒级),内存占用大,Qdrant/Milvus 默认使用
- IVF(Inverted File):聚类倒排索引,将向量分组,只搜索相近的簇
- PQ(Product Quantization):向量量化压缩,减少内存,牺牲一点精度
主流选择:HNSW 用于高性能场景,IVF_PQ 用于大规模内存受限场景。
LLM 原理
31. 什么是大语言模型(LLM)?
LLM(Large Language Model)是基于 Transformer 架构、在海量文本数据上预训练的神经网络模型。
- 参数规模:数十亿到数千亿(GPT-3 1750亿)
- 能力:文本生成、理解、翻译、推理、代码生成等
- 原理:自回归(Autoregressive)预测下一个 Token
- 训练阶段:预训练 → 指令微调(SFT)→ RLHF(人类反馈强化学习)
代表模型:GPT-4(OpenAI)、Claude(Anthropic)、Qwen(阿里)、Llama(Meta)。
32. Transformer 架构核心原理是什么?
Transformer 核心是 Self-Attention 机制,彻底摒弃了 RNN 的序列依赖。
1 | 输入 → Embedding + Positional Encoding |
关键创新:
- 并行计算:不同 Token 可并行计算 Attention,训练速度远超 RNN
- 长程依赖:任意两个位置直接计算 Attention,O(1) 路径长度
- 多头注意力:不同 Head 关注不同语义关系
33. Self-Attention 的计算流程是什么?
1 | 输入 X → 三个线性变换 → Q(Query)、K(Key)、V(Value) |
步骤:
- 输入向量乘以 Wq、Wk、Wv 得到 Q、K、V 矩阵
- Q × Kᵀ 计算注意力得分矩阵(每对 Token 间的相关性)
- 除以 √d_k 缩放(防止 softmax 梯度消失)
- Softmax 归一化得到注意力权重
- 权重 × V 加权求和得到输出
多头(Multi-Head):用多组独立的 Q/K/V,并行计算多个 Attention,最后拼接,捕捉不同类型的语义关系。
34. 什么是 hallucination(幻觉)?为什么会发生?
幻觉:LLM 生成看似合理但实际上不准确或捏造的信息(错误事实、不存在的引用等)。
原因:
- 训练数据分布:模型学习的是统计模式,而非事实核查
- 自回归生成:逐 Token 生成,一旦走错方向会持续编造自洽内容
- 知识截止:训练数据有时效性,过期知识导致错误
- 过度自信:模型无法感知自身的不确定性边界
- Prompt 模糊:问题歧义导致模型猜测意图并填充内容
35. 如何减少大模型 hallucination?
- RAG:提供真实文档作为依据,要求模型只基于上下文回答
- Prompt 设计:明确要求”如果不确定请说不知道”,设置 No-answer 兜底
- Temperature 降低:减小随机性(temperature=0 最确定性)
- CoT(Chain of Thought):让模型先推理再回答,减少跳跃
- Self-Consistency:多次采样取一致性高的答案
- Faithfulness 验证:生成后检查答案是否有原文支撑
- RLHF/RLAIF:通过人类反馈训练模型拒绝回答不确定内容
36. LLM 为什么推理成本高?
- 参数量巨大:GPT-4 估计约 1.8 万亿参数,每次前向传播需海量矩阵运算
- 自回归串行生成:每个 Token 需要完整前向传播,无法并行(只能 batch 并行)
- KV Cache 内存:存储每层的 Key-Value 矩阵,长上下文时显存占用爆炸
- Attention 复杂度:标准 Attention 是 O(n²)(n 为 Token 数),长序列成本极高
- GPU 依赖:需要高端 GPU(A100/H100),硬件成本高
优化手段:量化(INT8/INT4)、FlashAttention、KV Cache 复用、推测解码(Speculative Decoding)。
37. Temperature、Top-p、Top-k 有什么区别?
| 参数 | 含义 | 建议值 |
|---|---|---|
| Temperature | 控制输出随机性。越高越随机发散,越低越确定保守 | 创意任务 0.7-1.0;精确任务 0-0.3 |
| Top-k | 每步只从概率最高的 k 个 Token 中采样 | 通常 40-100 |
| Top-p(Nucleus Sampling) | 从累积概率达到 p 的最小 Token 集合中采样 | 通常 0.9-0.95 |
实践中:通常 temperature + top-p 联合使用;精确问答用低 temperature(00.2),创意写作用高 temperature(0.71.0)。
Tool Calling & Prompt
38. 什么是 Tool Calling?
Tool Calling(也称 Function Calling)是 LLM 的能力,允许模型输出结构化的工具调用请求,而非纯文本:
1 | { |
流程:
- 将可用工具(工具名、参数描述)写入 System Prompt
- LLM 判断需要工具时输出 JSON 格式的调用请求
- 应用层解析并实际执行工具
- 将执行结果作为 Tool Message 返回给 LLM
- LLM 基于结果继续生成最终回答
LangChain4j 用 @Tool 注解自动处理整个流程。
39. 什么是 Prompt Engineering?
Prompt Engineering 是通过精心设计输入提示来引导 LLM 输出期望结果的技术:
常用技巧:
- 角色设定:
你是一个专业的 Java 架构师 - Few-shot 示例:提供 2-5 个输入输出示例
- CoT(思维链):
请一步步思考 - 格式约束:
用 JSON 格式返回,包含 name 和 score 字段 - 约束条件:
只基于以下文档回答,不要使用其他知识 - 分步拆解:将复杂任务拆成多个子任务 Prompt
40. ChatGPT 的 system / user / assistant role 有什么作用?
| Role | 作用 | 示例 |
|---|---|---|
| system | 设置 AI 的行为规则、角色、约束,整个对话生效 | 你是一个专业客服,只回答产品相关问题 |
| user | 用户的输入/提问 | 我的订单什么时候发货? |
| assistant | AI 的历史回复(用于多轮对话上下文) | 您好,请提供订单号... |
System Message 权重最高,优先级 system > user > assistant。在 RAG 场景中,检索到的文档通常拼入 system 或 user message 中。
41. LangChain4j 如何实现 Tool 调用?
1 | // 1. 定义 Tool |
42. LangChain4j 如何返回结构化 JSON?
方式一:AiService 接口返回 POJO(推荐)
1 | record ProductInfo(String name, double price, String category) {} |
方式二:使用 JsonOutputParser
1 | // 在 Prompt 中要求 JSON 格式 + 显式解析 |
方式三:OpenAI JSON Mode
1 | OpenAiChatRequestParameters.builder() |
43. LangChain4j 如何实现 prompt template?
1 | // 方式一:@SystemMessage + @UserMessage 注解 |
44. 如何设计 Prompt 管理系统?
- 版本控制:Prompt 存数据库,带版本号和 tag(dev/prod),支持回滚
- 模板化:参数化变量,同一 Prompt 复用于不同场景
- A/B 测试:不同版本 Prompt 灰度分流,对比效果
- 热更新:不重启服务更新 Prompt(数据库/Redis 存储 + 定时刷新)
- 评估绑定:每个 Prompt 关联评估指标(效果、成本、延迟)
- 审计日志:记录修改人、时间、改动内容
1 | // 从数据库动态加载 Prompt |
45. 如何评估 Agent 的执行效果?
- 任务完成率:最终是否完成用户目标(人工标注 or LLM-as-Judge)
- 步骤正确率:中间工具调用是否合理(对比 golden trace)
- 工具使用效率:是否有冗余的工具调用、无效循环
- 延迟:完成任务所需总时间、工具调用次数
- 成本:消耗 Token 数量
- 幻觉率:最终答案是否基于事实
- 工具链路追踪:通过 LangSmith/Phoenix 等平台记录每步推理和工具调用
Java / Spring AI / LangChain4j
46. 什么是 AI Service(LangChain4j)?
AI Service 是 LangChain4j 的核心抽象,通过Java 接口 + 注解自动生成 AI 功能实现:
1 | interface CustomerSupportAgent { |
隐藏了 Prompt 构建、工具调用循环、Memory 管理等底层细节。
47. Spring AI 和 LangChain4j 有什么区别?
| 维度 | Spring AI | LangChain4j |
|---|---|---|
| 来源 | Spring 官方生态 | 独立开源项目 |
| 集成方式 | Spring Boot Starter,自动配置 | 手动配置,更灵活 |
| 成熟度 | 较新(2023年) | 更成熟,社区活跃 |
| API 风格 | Spring 惯用风格 | 偏 Python LangChain 移植 |
| 功能 | RAG、工具、向量存储 | RAG、工具、Memory、Agent、模板 |
| 适用场景 | Spring Boot 项目快速接入 | 需要精细控制 AI 逻辑 |
48. LangChain4j 和 Python LangChain 有什么区别?
| 维度 | Python LangChain | LangChain4j |
|---|---|---|
| 语言 | Python | Java |
| 生态 | 更丰富,模型/工具支持更多 | Java 生态集成好(Spring/MyBatis) |
| 更新频率 | 极快,API 变化频繁 | 相对稳定 |
| 性能 | 解释型,高并发需 async | JVM 高并发天然优势 |
| 企业应用 | 原型/数据科学领域 | 生产级 Java 后端服务 |
| Agent | LangGraph 功能强大 | AiServices 更简洁 |
49. 如何在 Spring Boot 中集成 LangChain4j?
1 | <!-- pom.xml --> |
1 | # application.yml |
1 |
|
50. Java 如何实现 streaming response?
1 | // LangChain4j StreamingChatLanguageModel |
51. Java 调用 OpenAI API 如何设计 SDK?
关键设计点:
- HTTP 客户端:OkHttp 或 Retrofit,支持同步/异步/流式
- 重试机制:指数退避重试(429 Rate Limit、5xx 错误)
- 超时配置:connectTimeout / readTimeout,流式需要更长 readTimeout
- 认证:API Key 通过 Header
Authorization: Bearer xxx传递 - 请求/响应 POJO:对应 OpenAI API 格式序列化/反序列化(Jackson/Gson)
- 流式解析:SSE 格式,逐行解析
data: {...}JSON - 错误处理:按 HTTP Status 和 error code 分类异常
1 | // 基于 OkHttp 的简化实现 |
52. Java LLM 服务如何做连接池管理?
1 | // OkHttp 连接池配置 |
注意事项:
- LLM API 调用延迟高(数秒),需配置足够的 readTimeout
- 流式响应不会释放连接,需控制并发流式请求数量
- 对不同模型/API 使用独立连接池(避免互相影响)
- 监控连接池使用率,超 80% 需扩容
工程化 & 可观测性
53. 如何实现 SSE 推送?
1 | // Spring Boot SSE 实现 |
前端用 EventSource 接收:const es = new EventSource('/events'); es.onmessage = e => console.log(e.data);
54. streaming response 如何实现?
- 服务端:使用
StreamingChatLanguageModel,通过StreamingResponseHandler回调逐 token 处理 - 传输协议:SSE(Server-Sent Events)—— HTTP 长连接,服务端推送;或 WebSocket 双向通信
- 响应头:
Content-Type: text/event-stream; Cache-Control: no-cache - 前端:
EventSourceAPI 接收 SSE;React/Vue 监听事件更新 UI - 中断处理:客户端断开时服务端需感知并停止生成(监听
emitter.onCompletion)
55. LLM 服务如何做缓存?
精确缓存: 相同 Prompt hash → Redis 缓存结果,TTL 按业务设置(适合固定模板问题)
语义缓存: 相似问题命中缓存(更智能):
1 | 1. Query → Embedding 向量 |
KV Cache 复用(Prompt Cache): OpenAI / Claude 支持对相同前缀 Prompt 的 KV Cache 复用,减少 Token 计算量(成本↓50%+)。
适用场景:FAQ 问答缓存、固定 System Prompt 缓存。
56. LLM 服务如何做限流?
1 | // 基于 Guava RateLimiter 令牌桶 |
限流维度:
- 用户级:每用户每分钟 N 次
- Token 级:每用户每天 N 个 Token
- 全局级:保护 LLM API Key 不超 Rate Limit
57. LLM 服务如何做降级?
1 | // Resilience4j CircuitBreaker + Fallback |
降级触发条件:响应超时、错误率超阈值、服务不可用。降级链路:主模型 → 备用模型 → 缓存 → 兜底文案。
58. 如何做模型 fallback?
1 | public class FallbackLlmService { |
触发条件:API 超时、Rate Limit(429)、服务不可用(5xx)、账单不足(402)。
59. 多模型调度如何实现?
策略:
- 按任务类型路由:代码生成 → GPT-4、简单 FAQ → GPT-3.5(成本优化)
- 按成本路由:优先低成本模型,复杂任务升级到高成本模型
- 负载均衡:多个相同模型实例 Round-Robin
- A/B 测试路由:按用户 ID hash 分流不同模型
1 | public ChatLanguageModel route(TaskContext ctx) { |
60. LLM 如何实现多租户?
- API Key 隔离:每个租户使用独立的 LLM API Key,实现成本和配额隔离
- Prompt 隔离:租户级 System Prompt(品牌、知识库、权限)
- 知识库隔离:向量数据库按 tenant_id 过滤,每个租户只检索自己的文档
- 配额管理:数据库记录每租户的 Token 用量,超配额降级或拒绝
- 数据安全:租户数据加密存储,禁止跨租户数据访问
1 | // 向量检索时注入租户过滤 |
61. LLM API 如何设计接口?
1 | // RESTful Chat API 设计 |
设计原则:
- 遵循 OpenAI 兼容接口(生态工具可直接复用)
- 支持 streaming(SSE)和 非 streaming 两种模式
- 统一错误码规范(4xx 客户端错误,5xx 服务端错误)
- 在 Response 中返回 Token 用量
62. LLM latency 如何优化?
| 优化手段 | 效果 |
|---|---|
| 流式返回(Streaming) | 用户感知首 token 时间大幅降低 |
| 模型选择 | GPT-4o-mini vs GPT-4,延迟差 3-5 倍 |
| Prompt 压缩 | 减少输入 Token,降低 TTFT(Time To First Token) |
| KV Cache 复用 | 相同前缀 Prompt 复用,减少计算 |
| 就近部署 | 选择距离用户最近的 API Region |
| 并行工具调用 | 多个工具并行执行,非串行 |
| 语义缓存 | 相似问题直接命中缓存,零 LLM 延迟 |
63. MCP(Model Context Protocol)是什么?
MCP 是 Anthropic 2024年提出的标准化 AI 与外部工具/数据源交互协议:
1 | [LLM / AI Agent] |
核心概念:
- Resources:暴露数据(文件、DB 记录)
- Tools:暴露可执行功能
- Prompts:预定义 Prompt 模板
意义:统一工具接入标准,MCP Server 可被任何兼容 MCP 的 AI 客户端复用,避免重复开发。
64. AI系统如何记录 Prompt 和 Response?
1 | // AOP 方式统一记录 |
存储:结构化日志 → Elasticsearch / ClickHouse(便于查询分析)。
65. AI系统如何做监控?
指标维度:
- 可用性:LLM API 成功率、错误率
- 延迟:P50/P95/P99 响应时间、TTFT(首 Token 时间)
- 吞吐量:每秒请求数(RPS)
- 成本:Token 消耗速率、每请求成本
- 业务指标:用户满意度、任务完成率
技术方案:
1 | 应用层 → Prometheus 埋点 → Grafana 大盘 |
LangChain4j 集成 Micrometer 可自动上报延迟、Token 使用指标。
66. AI系统如何做成本控制?
- 模型选型:按任务复杂度选择模型(简单任务用 GPT-4o-mini,复杂用 GPT-4o)
- Prompt 优化:压缩 System Prompt、减少冗余上下文
- 缓存:语义缓存高频相似问题(命中率 30%+ 可节省大量 Token)
- Prompt Cache:利用 Claude/OpenAI 的前缀缓存特性(长 System Prompt 只计算一次)
- Token 预算:设置 max_tokens 上限,防止超长回复
- 用量监控:实时监控各 UserId/TenantId 的 Token 消耗,设置预算告警
- 量化模型:自部署场景使用 INT4/INT8 量化模型
67. AI系统如何做权限控制?
1 | // 多层权限控制 |
关键控制点:API 认证(JWT/OAuth2)、功能权限(RBAC)、数据权限(租户隔离)、配额管理、内容审核。
68. 如何统计 token usage?
1 | // LangChain4j 通过 TokenUsage 获取 |
汇总分析:按用户/时间/模型维度聚合,ClickHouse 适合大规模 Token 用量 OLAP 分析。
69. 如何设计 AI evaluation pipeline?
评估架构:
1 | 测试数据集(问题+标准答案) |
工具推荐:RAGAS(RAG 评估)、DeepEval(通用 LLM 评估)、LangSmith(追踪+评估一体)。
70. 如何做 A/B test 比较不同模型?
1 | // 基于用户 ID hash 分流 |
关键设计:
- 分流策略:用户 ID hash(同用户体验一致)或随机分流
- 指标采集:记录每次请求的模型版本、延迟、Token 数、用户反馈(点赞/踩)
- 统计显著性:样本量足够(通常数千次)后用 t-test 判断差异是否显著
- 灰度控制:从 5% 流量开始,逐步扩大,监控异常指标
- 实验隔离:同一用户在实验期间保持同一组(避免体验割裂)
