# 面试知识点总结 > 基于本项目的技术栈,总结面试常问知识点 --- ## 一、LangChain 核心知识点 ### 1.1 LangChain Agent 机制 #### Q1: 什么是 LangChain Agent? 它与 Chain 的区别? | 特性 | Chain | Agent | |------|-------|-------| | 执行方式 | 固定流程,按顺序执行 | 动态决策,自主选择下一步 | | 工具调用 | 预定义,需手动编写 | 自动判断是否调用工具 | | 适用场景 | 固定流程 (如 RAG) | 需要推理和决策的场景 | **项目中的应用**: ```python # 使用 create_agent 创建 Agent agent = create_agent( model=ChatTongyi(model="qwen3-max"), tools=[rag_summarize, get_weather, get_user_id], system_prompt="你是一个智能助手" ) ``` #### Q2: 解释 ReAct 框架在 Agent 中的应用 **ReAct = Reasoning + Acting** ``` Thought: 我需要知道用户所在城市的天气 Action: get_weather Action Input: 深圳 Observation: 天气晴朗,26°C Thought: 现在我有天气信息,可以回答用户问题了 ``` **项目中的体现**: - 系统提示词明确要求遵循 ReAct 框架 - Agent 自动完成 "思考→行动→观察→再思考" 循环 - 最多支持 5 次工具调用 ### 1.2 LangChain Middleware 中间件机制 #### Q3: LangChain 中间件是什么? 如何实现? LangChain 中间件是 LangGraph 提供的钩子机制,用于在 Agent 执行过程中注入自定义逻辑。 **项目中的三种中间件**: 1. **wrap_tool_call** - 工具调用包装 ```python @wrap_tool_call def monitor_tool(request, handler): # 工具调用前 logger.info(f"执行工具: {request.tool_call['name']}") result = handler(request) # 调用实际工具 # 工具调用后 return result ``` 2. **before_model** - 模型调用前 ```python @before_model def log_before_model(state, runtime): # 每次调用 LLM 前记录日志 logger.info(f"即将调用模型,当前有 {len(state['messages'])} 条消息") return None ``` 3. **dynamic_prompt** - 动态提示词 ```python @dynamic_prompt def report_prompt_switch(request): is_report = request.runtime.context.get("report", False) if is_report: return load_report_prompts() # 切换为报告生成 Prompt return load_system_prompts() ``` #### Q4: 中间件的应用场景有哪些? | 场景 | 中间件类型 | |------|-----------| | 日志记录 | before_model, wrap_tool_call | | 性能监控 | wrap_tool_call | | 动态提示词 | dynamic_prompt | | 权限控制 | wrap_tool_call | | 结果缓存 | wrap_tool_call | --- ## 二、RAG (检索增强生成) ### 2.1 RAG 核心流程 ``` 用户 query │ ▼ ┌─────────────────┐ │ 向量检索 │ ← Chroma Retriever └────────┬────────┘ │ 返回 Top-K 相关文档 ▼ ┌─────────────────┐ │ 构建 Prompt │ ← 拼接 query + context └────────┬────────┘ │ ▼ ┌─────────────────┐ │ LLM 生成回答 │ ← 通义千问 └────────┬────────┘ │ ▼ 返回结果 ``` ### 2.2 关键面试题 #### Q5: 为什么需要 RAG? 直接用 LLM 不可以吗? | 方案 | 优点 | 缺点 | |------|------|------| | 直接 LLM | 简单 | 知识截止、可能幻觉、无法访问私域知识 | | RAG | 实时性、可引用私域知识、减少幻觉 | 增加复杂度、依赖检索质量 | #### Q6: RAG 中的关键环节有哪些? 1. **文档加载**: PyPDFLoader, TextLoader 2. **文本分片**: RecursiveCharacterTextSplitter - chunk_size: 每片大小 - chunk_overlap: 重叠区域 (保持上下文) - separators: 分隔符优先级 3. **向量化**: Embedding 模型 4. **向量存储**: Chroma 5. **相似度检索**: Cosine similarity, Top-K 6. **结果拼接**: Query + Context → Prompt #### Q7: 如何优化 RAG 效果? | 优化方向 | 方法 | |----------|------| | 检索质量 | 调整 chunk_size、overlap、使用 better embedding | | 召回率 | 增加 Top-K、使用混合检索 | | 排序rerank | 使用 rerank 模型二次排序 | | Prompt 工程 | 优化 RAG Prompt 模板 | ### 2.3 项目中的 RAG 实现 ```python # rag_service.py class RagSummarizeService: def rag_summarize(self, query: str) -> str: # 1. 向量检索 context_docs = self.retriever.invoke(query) # 2. 拼接上下文 context = "" for doc in context_docs: context += f"[参考资料]: {doc.page_content} | {doc.metadata}\n" # 3. 调用 LLM 生成 return self.chain.invoke({ "input": query, "context": context }) ``` --- ## 三、向量数据库 (Chroma) ### 3.1 Chroma 核心概念 | 概念 | 说明 | |------|------| | Collection | 类似表,存储一类文档 | | Embedding Function | 向量化函数 | | Document | 包含 page_content 和 metadata | | Retriever | 检索器,支持相似度搜索 | ### 3.2 面试题 #### Q8: Chroma 的优势? - 轻量级,易于部署 - Python 原生,集成方便 - 支持持久化存储 - 与 LangChain 无缝集成 #### Q9: Chroma 与其他向量库 (Milvus/Pinecone) 的区别? | 特性 | Chroma | Milvus | Pinecone | |------|--------|--------|----------| | 部署方式 | 本地/嵌入 | 服务端 | SaaS | | 规模 | 中小 | 大规模 | 大规模 | | 成熟度 | 一般 | 高 | 高 | --- ## 四、Streamlit Web 开发 ### 4.1 项目中的应用 ```python # app.py import streamlit as st st.title("智扫通智能机器人客服") # 会话状态管理 if "agent" not in st.session_state: st.session_state["agent"] = ReactAgent() # 聊天记录 for message in st.session_state["message"]: st.chat_message(message["role"]).write(message["content"]) # 用户输入 prompt = st.chat_input() # 流式输出 if prompt: stream = agent.excute_stream(prompt) st.chat_message("assistant").write_stream(capture(stream)) ``` ### 4.2 关键面试题 #### Q10: Streamlit 的核心机制? - **声明式 UI**: 通过 st.xxx() 声明组件 - **脚本式**: 每次交互重新运行整个脚本 - **状态管理**: session_state 保持会话状态 - **热重载**: 修改代码自动刷新 #### Q11: 如何实现流式输出? ```python # 方法1: write_stream st.write_stream(generator_function) # 方法2: 自定义 (本项目使用) def capture(generator, cache_list): for chunk in generator: cache_list.append(chunk) for char in chunk: time.sleep(0.05) # 模拟打字效果 yield char ``` --- ## 五、设计模式 ### 5.1 工厂模式 (Factory Pattern) ```python # model/factory.py class BaseModelFactory(ABC): @abstractmethod def generator(self) -> Optional[Embeddings | BaseChatModel]: pass class ChatModelFactory(BaseModelFactory): def generator(self) -> Optional[BaseChatModel]: return ChatTongyi(model=rag_conf["chat_model_name"]) class EmbeddingsFactory(BaseModelFactory): def generator(self) -> Optional[Embeddings]: return DashScopeEmbeddings(model=rag_conf["embeddings_model_name"]) ``` **好处**: 统一创建入口,便于后续更换模型 ### 5.2 配置中心化 所有配置集中在 config/ 目录的 YAML 文件中: - rag.yaml: 模型配置 - chroma.yaml: 向量库配置 - agent.yaml: Agent 配置 - prompts.yaml: Prompt 路径配置 ### 5.3 中间件模式 利用装饰器和钩子实现横切关注点: - 日志 - 监控 - 动态提示词切换 --- ## 六、工程实践 ### 6.1 日志管理 ```python # utils/logger_handler.py def get_logger(name: str = "Agent"): logger = logging.getLogger(name) # 双写: 控制台 + 文件 console_handler = logging.StreamHandler() file_handler = logging.FileHandler(log_file, encoding='utf-8') return logger ``` ### 6.2 路径管理 ```python # utils/path_tool.py def get_project_root(): cur_file = os.path.abspath(__file__) proj_dir = os.path.dirname(os.path.dirname(cur_file)) return proj_dir def get_abs_path(relative_path): return os.path.join(get_project_root(), relative_path) ``` ### 6.3 MD5 去重 ```python # vector_store.py # 通过 MD5 避免重复加载文档 md5_hex = get_file_md5_hex(path) if check_md5_hex(md5_hex): continue # 已存在,跳过 self.vector_store.add_documents(split_doc) save_md5(md5_hex) ``` --- ## 七、LLM & Embedding ### 7.1 通义千问 (Qwen) - **模型**: qwen3-max (阿里云) - **调用**: langchain_community.chat_models.tongyi.ChatTongyi ### 7.2 DashScope Embedding - **模型**: text-embedding-v4 - **用途**: 将文本转为向量 - **调用**: langchain_community.embeddings.DashScopeEmbeddings --- ## 八、常见面试扩展问题 ### Q12: 如何保证 Agent 工具调用的安全性? 1. **工具入参校验**: Pydantic 类型提示 2. **调用次数限制**: 最多 N 次 3. **工具白名单**: 只允许调用指定工具 4. **中间件监控**: 记录所有调用 ### Q13: Agent 如何实现"思考过程"可视化? ```python # 项目中的实现 for chunk in res: last_msg = chunk["messages"][-1] if last_msg.tool_calls: # 显示思考过程 print(f"工具调用: {last_msg.tool_calls}") ``` ### Q14: RAG 召回率低怎么排查? 1. 检查 chunk_size 是否合适 2. 检查 embedding 质量 3. 查看检索到的文档是否相关 4. 调整 Top-K 值 5. 检查分片是否有意义 (避免切断句子) ### Q15: 生产环境部署注意什么? 1. **API 限流**: 添加重试机制 2. **错误处理**: 工具调用失败处理 3. **日志**: 完整日志记录 4. **监控**: 调用次数、耗时监控 5. **缓存**: 热门 query 缓存结果