携程 AI Agent开发 二面
1. 你做的 Agent 项目,完整链路讲一下
完整链路一般是用户问题进入后,先做意图识别和 query 改写,再根据意图判断走纯 RAG、RAG + Tool,还是多 Agent workflow。检索阶段会做混合召回,再用 rerank 精排,拼接上下文后交给大模型生成。如果涉及订单、机票、酒店这类实时数据,会通过 function calling 调后端接口。最后返回答案时,会附上引用、置信度或者兜底话术。二面一般会继续追问每一层为什么这么设计,以及哪一层最容易出问题。
def agent_pipeline(query, user_profile):
intent = detect_intent(query)
rewritten_query = rewrite_query(query, user_profile)
docs = hybrid_retrieve(rewritten_query)
top_docs = rerank(rewritten_query, docs)[:5]
tool_result = None
if intent in ["flight_query", "hotel_query", "order_status"]:
tool_result = call_backend_tool(intent, query, user_profile)
prompt = build_prompt(
query=query,
docs=top_docs,
tool_result=tool_result,
user_profile=user_profile
)
answer = llm_generate(prompt)
return answer
2. 为什么这个场景要做 Agent,而不是只做 RAG
答:如果只是知识问答,比如退改签规则、会员权益、发票说明,RAG 基本够用,因为重点是把资料查准再回答。但旅游场景很多问题不是单轮问答,而是组合任务,比如“帮我看看明天上海飞北京最早的航班,再推荐离会场近的酒店”,这就需要拆任务、查实时数据、跨工具联动、汇总结果,单纯 RAG 不够。Agent 的价值在于把“理解、决策、调用、执行、反馈”串起来。
3. 线上 RAG 为什么要做混合检索,不能只用向量库吗
答:只用向量检索在语义泛化上好,但对航班号、酒店名、地名缩写、政策关键词这类精确匹配问题不稳定。只用关键词检索又容易漏掉语义相近表达。所以线上通常做 BM25 + 向量检索的混合召回,再统一排序。这样既保留精确匹配能力,也保留语义召回能力。
def hybrid_retrieve(query):
bm25_docs = bm25_search(query, topk=20)
vector_docs = vector_search(query, topk=20)
merged = {}
for d in bm25_docs:
merged[d["id"]] = {"doc": d, "score": d["bm25_score"] * 0.4}
for d in vector_docs:
if d["id"] not in merged:
merged[d["id"]] = {"doc": d, "score": 0.0}
merged[d["id"]]["score"] += d["vector_score"] * 0.6
ranked = sorted(merged.values(), key=lambda x: x["score"], reverse=True)
return [x["doc"] for x in ranked]
4. 你们的 rerank 是怎么做的
答:召回阶段会先拿到几十条候选文档,但这些文档顺序未必可靠,所以需要 rerank。常见做法是用 cross-encoder 或者专门的 reranker,把 query 和每个候选 doc 一起输入模型,重新打分,再选前几条给生成模型。这样可以明显降低无关内容进入 prompt 的概率,尤其对长 query、复杂 query 比较有效。
def rerank(query, docs, rerank_model, topk=5):
pairs = [(query, d["content"]) for d in docs]
scores = rerank_model.predict(pairs)
for d, s in zip(docs, scores):
d["rerank_score"] = float(s)
docs = sorted(docs, key=lambda x: x["rerank_score"], reverse=True)
return docs[:topk]
5. RAG 里 chunk 怎么切,规则文档和 FAQ 文档一样吗
答:不一样。FAQ 更适合按问答对切,因为每一条本身就语义完整;规则文档、合同文档、会员说明更适合按标题层级切,再辅以 overlap,保证上下文不断裂。如果是航变、酒店取消规则这种长文档,我一般会保留标题路径,比如“酒店规则-取消政策-节假日特殊条款”,这样检索回来后模型更容易理解上下级关系。
def split_with_overlap(text, chunk_size=300, overlap=50):
chunks = []
start = 0
while start < len(text):
end = min(start + chunk_size, len(text))
chunks.append(text[start:end])
if end == len(text):
break
start = end - overlap
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏聚焦 AI-Agent 面试高频考点,内容来自真实面试与项目实践。系统覆盖大模型基础、Prompt工程、RAG、Agent架构、工具调用、多Agent协作、记忆机制、评测、安全与部署优化等核心模块。以“原理+场景+实战”为主线,提供高频题解析、标准答题思路与工程落地方法,帮助你高效查漏补缺.