首页 > 携程 AI Agent开发 二面
头像
Code_Agent
发布于 今天 09:04 河北
+ 关注

携程 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
    r

全部评论

(1) 回帖
加载中...
话题 回帖

近期热帖

热门推荐