Appearance
1. 什么是LangChain?它的核心组件有哪些?
LangChain 是一个开源框架,用于简化基于大型语言模型的应用开发。它提供模块化的工具和接口,使开发者能够将 LLM 与外部数据源、工具和系统连接,用于构建聊天机器人、问答系统、Agent 等复杂应用。
核心组件
模型(Models)
封装与各种 LLM(如 OpenAI GPT、Claude、HuggingFace 模型等)的交互接口
包含
LLMs:输入文本,输出文本
Chat Models:输入与输出均为消息结构
提示(Prompts)
用于构建和管理输入给模型的 Prompt
提供 Prompt Templates、Example Selectors,用以动态生成结构化提示
索引(Indexes)
用于使 LLM 更好地利用外部文档数据,是 RAG 的基础。
包含:
文档加载器(Document Loaders):从文件、网页、数据库读取文档
文本分割器(Text Splitters):将长文本切分为可处理的小块
向量存储(Vector Stores):存储向量化的文档块并支持相似性检索
检索器(Retrievers):从向量库检索相关文档块
链(Chains)
将提示、模型、工具等组件按顺序组合成可执行逻辑
支持预置链(LLMChain、RetrievalQA)及自定义链
用于构建如“先检索 → 再生成”的复合流程
记忆(Memory)
用于保存对话上下文或状态,使系统具备连续性
支持 Buffer Memory、Summary Memory、Knowledge Graph Memory 等
Agent
让 LLM 拥有自主决策能力,可根据输入选择要调用的工具并规划多步操作
包含:LLM、工具集合、Agent 执行器(如 ReAct)
回调(Callbacks)
- 在应用执行的不同阶段插入自定义逻辑,用于日志、监控、流式输出等
举例类比记忆
可以把 LangChain 理解为“乐高积木套装”,每个组件(模型、提示、索引、链、Agent)都是积木块。
- 开发者通过组合这些积木块即可快速搭建一个完整的智能应用。
索引系统类似图书馆管理员:
文档加载器 = 负责把书运进图书馆
文本分割器 = 按章节整理
向量库 = 给每章贴好标签
检索器 = 根据查询快速找到最相关的章节
知识点易错提醒
只说 LangChain“封装了 LLM 调用”不够全面,核心价值是“组件化 + 可组合性”,让开发者无需从零搭建 RAG 或 Agent。
容易把“链(Chains)”和“Agent”混为一谈:
链是固定的流程
Agent 是动态决策、可调用工具
忽略索引系统在 RAG 中的关键地位也是常见错误
延伸面试提问及应答建议
1. 链(Chains)和 Agent 的本质区别是什么?
简答示例
链是固定步骤的流水线,而 Agent 能根据上下文动态选择下一步动作并调用工具。
关键要点清单
链:预定义流程
Agent:动态规划
Agent 需要推理能力(如 ReAct)
工具使用场景不同
回答模板
链强调固定结构;Agent 强调自主决策和工具调用。两者适用于不同复杂度的任务。
可能延伸追问
- 什么时候应该使用链,而不是 Agent?
应对建议:强调性能、稳定性、可控性较高时优先链;任务不确定性强时用 Agent。
2. LangChain中的链(Chains)和 Agent 有什么区别?
链(Chains)和 Agent 是 LangChain 中组织与执行 LLM 逻辑的两类核心机制,它们的主要差异在于“流程是否固定”与“决策是否动态”。
链(Chains)
定义
链代表一组预定义、固定顺序的调用流程。LLM、提示、工具等组件的执行步骤在创建链时就已经确定。
决策方式
流程是静态的,运行时严格按照既定步骤执行。
典型例子
LLMChain:输入 → 格式化提示 → 调用 LLM → 输出
RetrievalQA:检索 → 生成
(无论用户问什么,顺序始终不变)
适用场景
流程明确、步骤固定的任务。
灵活性
较低。
Agent
定义
Agent 将 LLM 作为“决策大脑”,根据当前任务动态决定调用哪些工具,以及下一步该怎么做。
决策方式
每一步由 LLM 进行推理(Reasoning),选择行动(Acting),流程不是预先确定的。
典型例子
问天气 → 使用搜索工具
问计算题 → 使用计算器
问文件内容 → 使用文件读取工具
适用场景
需要多工具交互、步骤不确定、需要智能决策的复杂任务。
灵活性
很高。
举例类比记忆
链 = 固定菜谱
按照步骤做菜,不允许自由发挥。Agent = 厨师
根据顾客要求与食材情况灵活决定怎么做菜。在真实应用中,Agent 甚至会在内部调用 Chains 完成子任务。
知识点易错提醒
容易误以为 Agent 是“更高级的链”。实际上,两者机制不同:
链 = 固定流程
Agent = 推理 + 工具调用
很多人忽略 Agent 内部依赖“LLM 推理能力”。如果提示设计不足,Agent 会出现工具选择错误或循环调用工具的问题。
面试常见误区是认为 Chains 能自动做动态决策,而这是 Agent 的功能。
延伸面试提问及应答建议
1. 什么时候应该用链,什么时候应该用 Agent?
简答示例
流程稳定时用链;任务步骤会因用户输入而变化、需要工具交互时用 Agent。
关键要点清单
链:高可控、高稳定
Agent:高灵活、能自动规划
性能开销差异(Agent 更重)
开发调试复杂度差异
回答模板
如果任务流程固定,使用链能确保稳定和高效;当任务需要动态决策或工具选择时,应使用 Agent。
可能延伸追问
- Agent 性能更差吗?
应对建议:肯定需要更多推理步骤,可强调可通过减少工具数量、限制思考轮次等方式优化。
2. Agent 为什么需要 ReAct 或 Self-Ask 等执行器?
简答示例
这些执行器提供一种规范的“思考—行动—观察”结构,让 LLM 可以可控地规划步骤和调用工具。
关键要点清单
结构化推理
降低幻觉
有助于调试
提升工具调用准确性
回答模板
执行器为 Agent 提供推理框架,确保其行动可解释、工具调用路径明确,从而提高稳定性和正确性。
可能延伸追问
- 如果没有 ReAct 会怎样?
应对建议:说明模型会随意调用工具、出现混乱输出或自我循环,难以控制行为。
2. LangChain 的索引系统在 RAG 中起什么作用?
简答示例
索引系统负责文档加载、切分、向量化与检索,是 RAG 的基础设施。
关键要点清单
文档结构化
高效检索
与模型生成结合
改善长文本理解
回答模板
索引系统承担数据整理与检索的任务,使 LLM 能根据查询拿到正确的信息来源。
可能延伸追问
- 为什么要先切分再向量化?
应对建议:说明长文直接向量化容易丢失语义,需要更细粒度片段来提高检索精度。
3. LangChain表达式语言(LCEL)是什么?它有什么好处?
LangChain表达式语言(LangChain Expression Language, LCEL)是LangChain v0.1版本后引入的一种声明式的方式来组合和构建链(Chains)以及其他LLM应用组件。它使得定义复杂处理流程更加简洁、直观和强大。
核心思想: LCEL的核心思想是将LangChain的各种组件(如PromptTemplate, LLM, ChatModel, Retriever, OutputParser等)视为可调用对象(Runnables),并使用类似Unix管道的| (pipe)操作符将它们连接起来,形成处理流水线。
python
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
# 定义提示模板
prompt = ChatPromptTemplate.from_template("给我讲一个关于{topic}的笑话")
# 定义模型
model = ChatOpenAI()
# 定义输出解析器
output_parser = StrOutputParser()
# 使用LCEL构建链
chain = prompt | model | output_parser
# 调用链
result = chain.invoke({"topic": "程序员"})
print(result)在这个例子中:
prompt接收一个包含topic的字典作为输入。 |操作符将prompt的输出传递给model。 model接收格式化后的提示,调用LLM,输出一个AIMessage。 |操作符将model的输出传递给output_parser。 output_parser解析AIMessage,提取内容并返回字符串。 LCEL的好处:
统一的接口(Runnable):
所有LCEL兼容的组件都实现了相同的Runnable接口,支持invoke, batch, stream, ainvoke, abatch, astream等方法。 这使得组件可以无缝连接,并且提供了同步、异步、批处理、流式处理的统一支持。 简洁性与可读性:
使用|操作符连接组件,代码更简洁,处理流程一目了然,易于理解和维护。 相比之前定义链的方式(如LLMChain(llm=model, prompt=prompt)),LCEL更直观。 组合性(Composability):
可以轻松地将多个Runnable对象组合成更复杂的流水线。 支持并行执行(RunnableParallel)、条件执行等高级组合方式。 流式处理(Streaming)支持:
LCEL原生支持流式输出。如果链中的任何组件支持流式处理,整个链就可以流式返回结果,这对于构建实时交互应用(如聊天机器人)非常重要。 只需调用.stream()或.astream()方法即可。 异步与批处理支持:
开箱即用地支持异步调用(ainvoke, abatch, astream)和批处理(batch, abatch),提高了效率和并发能力。 可观测性与调试:
LCEL集成了LangSmith等工具,可以方便地追踪和调试链的执行过程,查看每一步的输入输出。 回退与重试:
可以方便地为Runnable对象配置回退(Fallbacks)和重试(Retries)逻辑,增强应用的鲁棒性。 LCEL是LangChain推荐的构建链和应用的方式,它极大地简化了开发流程,并提供了更强大、更一致的功能。
举例类比记忆
可以把 LCEL 想象成程序员世界里的“积木流水线”。每块积木(Prompt、LLM、Parser)都能独立工作,而 LCEL 的管道符号就像把积木按顺序拼起来,形成完整的传送带。
类似 Unix 的 pipe:
cat → grep → awk,只是把文本生产线换成了 LLM 的推理生产线。
知识点易错提醒
很多人只记住“LCEL 用 | 连接组件”,但忽略它真正的核心是“统一的 Runnable 接口”,这是它能支持同步、异步、批处理、流式输出的关键。
容易混淆 LCEL 与传统 LLMChain,忽视 LCEL 更强的可组合性(并行、条件、回退重试)。
面试中只强调“代码更简洁”,会显得理解浅,需要补充:可观测性、流式输出、可扩展性才是面试加分点。
延伸面试提问及应答建议
1. 为什么 LCEL 比传统 LLMChain 更适合复杂应用?
示例答句:
LCEL 基于统一的 Runnable 接口,可以灵活组合串行、并行、条件和流式处理逻辑,而传统 LLMChain 的组合能力有限,因此 LCEL 更适合构建复杂的应用流水线。
要点清单:
Runnable 接口统一
可组合性强:串行、并行、条件
支持流式与异步
更好可观测性和调试能力
回答模板:
“LCEL 的优势主要体现在统一接口和更强的组合能力,它允许在同一套 API 下灵活组合处理步骤,同时原生支持流式、异步和调试功能,因此更适合复杂链路。”
可能延伸追问与应对:
- LCEL 的 stream 和 astream 在链路中如何传播?
答:任意一个组件支持流式,该链就可以流式输出。组件之间通过生成器持续返回部分 token。
2. LCEL 是如何实现并行执行的?
示例答句:
LCEL 通过 RunnableParallel 将多个 Runnable 作为字典并行执行,并将结果以字典形式返回。
要点清单:
RunnableParallel 的字典式结构
并行运行多个组件
结果自动组合
回答模板:
“并行性由 RunnableParallel 提供,通过字典结构同时执行多个步骤,再将结果组合返回。”
可能延伸追问与应对:
- 可以结合检索和模型推理一起并行吗?
答:可以,检索器和 LLM 都是 Runnable,可直接并行。
3. LCEL 的流式输出如何在应用中使用?
示例答句:
只要链中某个组件支持流式,整个 LCEL 管道即可通过 stream 或 astream 方法实时返回 token。
要点清单:
流式传播机制
.stream()和.astream()应用场景:聊天机器人、实时展示
回答模板:
“流式能力来自底层 Runnable 的 token 级输出,通过 stream/astream 可将其向上传播到整个链,适用于需要实时反馈的应用。”
可能延伸追问与应对:
- 流式处理是否会影响性能?
答:总体影响不大,核心开销仍在 LLM 侧,LCEL 负责传输 token。
4. LangChain中的文本分割器(Text Splitters)有什么作用?为什么需要它?
LangChain中的文本分割器(Text Splitters)的主要作用是将长文档分割成更小的、语义上连贯的文本块(Chunks)。
为什么需要文本分割器
LLM上下文窗口限制
大型语言模型都有其可以处理的最大输入长度限制(上下文窗口大小),通常以Token数量衡量。如果直接将非常长的文档作为输入传递给LLM,会超出其处理能力,导致错误或信息截断。分割成小块可以确保每个块都在LLM的处理范围内。RAG检索效率与相关性
在RAG场景中,需要将文档块嵌入(Embedding)并存储在向量数据库中进行检索。如果文档块太大,其向量表示可能过于泛化,难以精确匹配用户的具体查询。较小的、语义集中的块更容易与特定查询建立高相关性,从而提高检索的准确性。检索到更小的块也意味着传递给LLM生成答案的上下文更精炼、噪声更少。处理成本与速度
处理(嵌入、存储、检索、传递给LLM)较小的文本块通常比处理整个大文档更快、成本更低。保留语义完整性
好的文本分割器会尝试在语义边界(如段落、句子)进行分割,而不是随意切断文本。一些分割器(如RecursiveCharacterTextSplitter)会尝试按不同的分隔符(如\n\n, \n, , ``)递归地分割,以尽可能保持块的语义连贯性。
常见的文本分割器类型
CharacterTextSplitter:按固定字符数分割,可指定分隔符。
RecursiveCharacterTextSplitter:推荐的通用分割器,会按优先级列表中的分隔符尝试分割,更可能在自然的语义断点处分割。
TokenTextSplitter:按Token数量分割,需要分词器(Tokenizer)来计算Token数,更精确匹配LLM的Token限制。
MarkdownTextSplitter:专门用于分割Markdown文档,会考虑Markdown结构(如标题、列表)。
PythonCodeTextSplitter, JavaScriptTextSplitter 等:专门用于分割特定编程语言的代码,会考虑代码结构。
关键参数
chunk_size:每个块的目标大小(字符数或Token数)。
chunk_overlap:相邻块之间的重叠大小,设置重叠可以帮助保留块边界处的上下文信息,防止语义被割裂。
选择合适的文本分割器和参数对于构建高效、准确的LLM应用(尤其是RAG系统)至关重要。
举例子类比记忆
文档就像一张超大的地图,LLM的上下文窗口是你的背包容量,Text Splitter就像把地图裁切成小块放入背包,既方便携带又保证信息完整。
Chunk_overlap类似在裁切地图时保留的重叠区域,确保你从一块地图跳到另一块时不会丢失路线信息。
知识点易错提醒
不要只强调“分割文档”,必须理解其背后的原因:上下文窗口限制、检索效率、处理成本与语义保留。
忽略chunk_overlap会导致语义断裂,尤其在RAG系统中容易影响检索结果质量。
延伸面试提问及应答建议
为什么RAG系统中需要较小的文档块而不是整个文档?
简答:小块更容易与特定查询匹配,提高检索精度,同时传递给LLM的上下文更精炼,降低噪声。Chunk_overlap设置过大或过小有什么影响?
简答:过大增加计算和存储成本,过小可能导致语义断裂,尤其影响生成答案的连贯性。在代码文档中选择分割器时,有哪些考虑?
简答:选择PythonCodeTextSplitter等专门分割器,保留代码结构,避免随意切割函数或语句,保证语义完整。
5. LangChain中的输出解析器(Output Parsers)是做什么的?举例说明
LangChain 中的输出解析器用于将 LLM 返回的原始文本转换为结构化格式,确保应用程序能够直接使用这些结果。其核心目标是让“不稳定”“不可控”的自然语言输出变成可程序化处理的数据结构,如 JSON、列表或特定对象。
输出解析器的作用
接收 LLM 的自然语言输出
根据预设规则将其解析为结构化数据
在提示阶段提供格式化指令,使 LLM 按所需格式输出
保证下游任务可以稳定地消费模型结果
为什么需要输出解析器
LLM 的生成内容往往无结构、自由表达
应用程序通常期望明确格式,如
JSON
Python list
特定 schema
输出解析器负责将自然语言映射为可操作的数据结构
在调用 LLM 前向提示中注入格式要求,提高解析成功率
工作流程
可选:生成格式化指令,将其注入最终提示
接收模型返回的原始文本或消息对象
按规则解析:如分隔符解析、JSON 解析、自定义 schema 解析
输出结构化结果供程序直接使用
常见示例
StrOutputParser
作用:提取 LLM 返回消息的内容为字符串
用途:通常作为链末端的输出转换
示例:
输入:AIMessage(content="Hello World")
输出:"Hello World"
CommaSeparatedListOutputParser
作用:解析模型生成的逗号分隔字符串,将其转换为 Python 列表
格式化指令示例:
输入示例:
"apple, banana, orange"解析结果:
[
["apple", "banana", "orange"]
]
举例类比记忆
输出解析器就像“数据清洗机器人”:
LLM 输出的自然语言类似于散乱的原料,而解析器负责将这些原料加工成标准化的半成品。类比 CSV 导入工具:
你不会直接处理原始文本文件,而是用解析器将其变成结构化表格。
知识点易错提醒
容易误解输出解析器只是“字符串处理”,但其关键价值在于
为提示提供格式指令
保证解析稳定性和可复用性
忽略异常处理:
若 LLM 未按格式生成,解析器可能失败,因此面试回答需要提到“解析失败处理策略”。
延伸面试提问及应答建议
可能提问:输出解析器与 PromptTemplate 有什么区别?
示范回答:
PromptTemplate 负责“输入格式化”,而输出解析器负责“输出结构化”。前者控制模型如何接收信息,后者控制模型如何输出信息,它们构成链式调用的前后两端。
关键要点:
PromptTemplate = 输入格式
Output Parser = 输出格式
两者一起确保链式调用稳定
延伸追问:如果 LLM 输出格式不符合预期怎么办?
应答建议:说明需要 retry、fallback、严格指令或使用更强 schema(如 PydanticOutputParser)。
可能提问:何时需要自定义输出解析器?
示范回答:
当业务需要特定结构(如多字段对象、嵌套结构、代码块提取)且内置解析器无法满足需求时,就需要自定义解析逻辑。
关键要点:
特定业务结构
自定义校验逻辑
上下文一致性处理
延伸追问:如何保证自定义解析器解析稳定?
建议回答:强调 schema 约束、严格格式化指令、error handling、模型温度调低等策略。
6. LangChain如何实现RAG(检索增强生成)?涉及哪些核心组件?
LangChain通过其索引(Indexes)和链(Chains)模块提供了构建RAG应用的能力。RAG的核心思想是在LLM生成答案前,通过检索外部知识库为模型提供上下文,从而提升回答的准确性与事实性。
LangChain实现RAG的核心组件
文档加载器(Document Loaders)
作用:从PDF、网页、数据库、Notion、Google Drive等来源加载原始文档。
示例:PyPDFLoader、WebBaseLoader、CSVLoader。
文本分割器(Text Splitters)
作用:将长文档分成语义完整的文本块,便于后续嵌入和检索。
示例:RecursiveCharacterTextSplitter、CharacterTextSplitter、TokenTextSplitter。
嵌入模型(Embedding Models)
作用:将文本块转换为高维向量,用于语义相似度匹配。
示例:OpenAIEmbeddings、HuggingFaceEmbeddings。
向量存储(Vector Stores)
作用:保存文本块及其向量,并支持高效向量相似度搜索。
示例:FAISS、Chroma、Pinecone、Weaviate、Milvus。
检索器(Retrievers)
作用:将用户查询向量化,并在向量库中搜索最相关的文本块。
特性:支持MMR、多查询检索、上下文压缩等。
实现方式:vectorstore.as_retriever()。
链(Chains)
作用:将检索结果与用户查询组合成提示,并交给LLM生成最终答案。
常用链:RetrievalQA、ConversationalRetrievalChain。
LangChain中的典型RAG流程
数据准备(离线)
使用Document Loaders读取文档。
使用Text Splitters划分文本。
通过Embedding Models生成向量。
将向量与文本块存储到Vector Stores。
查询处理(在线)
用户发送问题。
Retriever向量化查询并检索相关文档。
RetrievalQA链构建提示并调用LLM生成答案。
返回回答给用户。
举例类比记忆
将RAG理解为“开卷考试”。LLM是学生,向量数据库是资料库,Retriever负责从图书馆找到最相关的页码,再交给学生回答问题。
Document Loader像“扫描仪”,Text Splitter像“裁纸刀”,Embedding像“把内容转成坐标”,Vector Store像“图书馆索引系统”,Retriever像“图书管理员”。
知识点易错提醒
常忽略检索器与向量库的区别,导致概念混淆。向量库负责存储,检索器负责找。
容易忘记Text Splitter对最终检索效果影响极大,分块太大或太小都会导致召回质量下降。
误以为RetrievalQA链只是一层包装,而忽略它在提示构建中的重要作用。
延伸面试提问及应答建议
为什么Text Splitter是RAG效果的关键?
简答:因为LLM有上下文窗口限制,且块尺寸直接影响检索精度与召回内容的质量,合适的分块能提供更相关、更集中、更可用的上下文。
应答建议:
示例答句:
合适的分块策略可以确保每个文本块既包含足够的语义,又不会过长导致检索不准,因此直接决定了RAG系统能否找到正确的知识点。关键要点清单:
上下文窗口限制
语义完整性
检索匹配精度
嵌入质量
回答模板:
在RAG系统中,分块策略对检索效果至关重要,因为它决定了模型在检索阶段能否获得结构良好且语义集中的信息,从而影响最终生成答案的质量。可能延伸追问:分块大小如何选择?
应对:可以根据任务选择固定长度分块或递归字符分块,实际常靠实验确定最佳chunk size。
RetrievalQA链与ConversationalRetrievalChain的区别是什么?
简答:前者面向单轮问答,后者支持多轮上下文与历史对话记忆。
应答建议:
示例答句:
RetrievalQA适用于一次性提问,而ConversationalRetrievalChain会结合历史对话进行检索,更适合多轮问答或智能客服场景。关键要点清单:
是否使用对话历史
检索策略
应用场景差异
回答模板:
RetrievalQA主要用于处理单轮问答,而ConversationalRetrievalChain会将用户过去的提问与回答作为额外上下文,从而实现更连贯的检索与生成。可能延伸追问:如何管理对话历史?
应对:通常使用memory模块,也可以利用压缩检索减少冗余历史内容。
7. 为什么项目里面不用 LangChain 去做这些事?
在项目中没有使用 LangChain,主要基于以下几个方面的综合考量:
框架封装问题
LangChain 封装链路较重,调试和定位问题较难。
中间层多,资源开销大,性能低下,精细性能优化困难。
作为框架,它有自身设计哲学,一旦接入就必须遵循,但和项目需求存在冲突。
RAG 系统适配问题
项目采用复杂的混合 RAG 架构:Faiss + Neo4j(语义检索 + 图谱检索)。
LangChain 虽有 RAGChain,但不够灵活,无法很好支持混合检索和链路控制。
自行实现可以深度定制 RAG 流程,更好地融合二者知识。
技术栈兼容性问题
项目主要技术栈为 Java,大部分 API 只有 Java 版本,如访问数据库、缓存、调用 RPC 接口、上报 Hive 表、埋点监控等。
LangChain 以 Python 为主,虽然后续有 Java 版本 LangChain4J,但在系统设计时还未成熟。
若强行使用 LangChain,需要跨服务通信多次,成本高、维护复杂、稳定性差。
综合权衡结论
虽然自行实现代码量大,但在性能、链路控制、RAG 深度定制和技术栈匹配方面有明显优势。
选型追求与工程背景、团队能力、业务目标匹配,而非最流行工具。
LangChain 是优秀工具,但在当前项目中并不最适合。
举例子类比记忆
LangChain 类似“全功能瑞士军刀”,功能多但体积大,携带和使用受限制。
自行实现相当于“定制手工工具”,专门针对特定任务优化,虽然制作成本高,但效率和适用性最佳。
知识点易错提醒
易错点:认为“不用 LangChain 是因为它不好”,实际上是“好工具不一定适合特定工程背景和技术栈”。
易混淆:LangChain 能做 RAG 并不意味着它适合所有混合检索架构,尤其是需要高定制化的场景。
延伸面试提问及应答建议
问:LangChain 的优势和劣势分别是什么?
答:优势是封装完善、生态丰富、适合快速构建链式应用;劣势是封装过重、调试难、性能优化受限、对特定混合架构支持不灵活。问:为什么项目中选择自行实现而不是等待 LangChain4J 成熟?
答:因为项目设计阶段需要立即可用的、与现有 Java 技术栈和混合 RAG 流程兼容的方案,等待框架成熟会影响业务交付。问:在使用框架和自行实现之间,如何做选型?
答:评估维度包括性能需求、链路控制、架构兼容性、团队技术栈能力和业务目标;框架方便快速开发,但可能牺牲精细控制,自行实现灵活但开发成本高。
