携程 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面试实战专栏 文章被收录于专栏

本专栏聚焦 AI-Agent 面试高频考点,内容来自真实面试与项目实践。系统覆盖大模型基础、Prompt工程、RAG、Agent架构、工具调用、多Agent协作、记忆机制、评测、安全与部署优化等核心模块。以“原理+场景+实战”为主线,提供高频题解析、标准答题思路与工程落地方法,帮助你高效查漏补缺.

全部评论
礼貌蹲一下一二面时间线
点赞 回复 分享
发布于 今天 10:02 上海

相关推荐

03-21 21:54
吉林大学 Java
项目是RAG+点评,全程1h30min用英语简单介绍自己1.平时都是怎么学技术的2.线程和协程的区别?3.了解过线程池吗,为什么要用到线程池4.知道哪几种线程池?5.把一个任务扔进线程池会用什么方式处理6.知道哪几种拒绝策略,基于什么样的场景会去选择这样的拒绝策略7.多线程场景下,如何保证线程安全8.Synchronized&nbsp;ReentrantLock的区别?9.发生死锁的条件?10.使用锁的时候有哪些注意事项,怎么样加锁会比较好一点11.JVM内存结构12.int变量和Object变量会放在哪个区域?13.GC算法各自适用的场景?14.ACID,原子性一致性怎么实现的15.优化一个索引或者设计一个索引,需要考虑哪些16.B+树结构,为什么要用B+树,有什么优点17.什么是空间局部性ai项目介绍18.系统架构大概是怎样的19.生产过程的数据怎么记录的20.为什么要用阿里的大模型21.分块策略怎么做的22.怎么评估检索效果23.如果问了一个知识库里没有的问题,系统怎么表现24.检索效果不好的话,如何排查和优化25.QPS特别高的话系统会有什么瓶颈第二个项目26.项目中redis的作用27.redis的IO模型28.redis为什么快29.为什么用Cache-Aside,为什么不用其他策略30.热点key该怎么处理31.分布式锁的维度?32.抢购过程整体链路?33.100万人同时抢一个商品怎么解决34.用户同时在多个分片抢购怎么解决35.为什么用MQ,有什么作用36.如何判断消费成功37.如何保证消息幂等性重问第一个项目38.假如系统10分钟内一直告警,运维agent怎么去处理,有什么好的优化方案手撕:LRU缓存
点赞 评论 收藏
分享
评论
点赞
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务