携程 AI Agent 开发一面

1、RAG 里的幻觉怎么解决?

RAG 幻觉一般来自三种情况:没有召回到正确证据、召回到了但排序不对、证据足够但模型还是自己补。解决也要对应分层。

第一层是提高文档质量和召回质量,比如切片更合理、用混合检索、做 query rewrite、加 metadata 过滤。第二层是重排层,用 rerank 模型让最相关证据排前面。第三层是生成层,要让模型严格基于证据回答,证据不足就拒答,不允许自由扩写。

如果从更抽象的角度看,幻觉问题本质上是“系统回答倾向强于证据约束”。所以真正要解决的是:让系统在信息不足时学会克制,而不是为了流畅性硬编一个完整答案。

2、LoRA 微调原理

LoRA 是 Low-Rank Adaptation,本质上是一种参数高效微调方法。它的核心思想不是去更新原始大模型里的全部参数,而是冻结原模型权重,只在某些线性层旁边额外挂两个低秩矩阵,让模型通过学习这两个小矩阵来完成任务适配。

假设原始线性层权重是,正常微调会直接更新 (W)。LoRA 则把增量写成:

其中,(r) 远小于 (d,k)。也就是说,大矩阵更新被拆成两个小矩阵相乘,从而显著降低可训练参数量和显存占用。

它的优点主要有三个:第一,训练参数少,显存压力小;第二,可以在多个任务上保存多个 LoRA adapter,不必保存多份完整模型;第三,部署时可以选择动态挂载或者合并回原权重。它常见地作用在 Attention 里的 Q、K、V、O 投影层,也可以作用在 MLP 层。

import torch
import torch.nn as nn

class LoRALinear(nn.Module):
    def __init__(self, in_features, out_features, r=8, alpha=16):
        super().__init__()
        self.weight = nn.Parameter(torch.randn(out_features, in_features), requires_grad=False)
        self.A = nn.Parameter(torch.randn(r, in_features) * 0.01)
        self.B = nn.Parameter(torch.zeros(out_features, r))
        self.scale = alpha / r

    def forward(self, x):
        base = x @ self.weight.t()
        lora = x @ self.A.t() @ self.B.t()
        return base + self.scale * lora

3、Function Calling 怎么设计更稳?

Function Calling 稳定性的关键不是把工具注册进去,而是工具 schema、候选筛选和执行保护。工具定义时要把名字、描述、参数类型、必填字段、约束范围写清楚。工具很多时,不要全部暴露给模型,应该先做意图识别,筛出少量可能相关的工具。

执行阶段不能直接相信模型吐出来的参数,程序必须做 JSON 解析、schema 校验、权限校验和幂等控制。对有副作用的工具,比如下单、改签、退款申请、发短信通知,一定要有确认和审计,不能让模型自由执行。

tool_schema = {
    "name": "query_flight_status",
    "description": "根据航班号查询航班状态",
    "parameters": {
        "type": "object",
        "properties": {
            "flight_no": {"type": "string"},
            "date": {"type": "string"}
        },
        "required": ["flight_no", "date"]
    }
}

4、Prompt 工程你怎么理解?

Prompt 工程本质上是通过设计输入结构,让模型更稳定地完成任务,而不是单纯把提示词写长。它关注的是角色设定、任务目标、输出格式、约束条件、示例设计、上下文组织和拒答边界。

在 Agent 系统里,Prompt 工程往往和模型、工具、RAG、记忆一起配合。比如知识问答要强调“仅基于证据回答”,工具调用要强调“只输出 JSON 参数”,多轮改写要强调“不要改变用户原意”。Prompt 不是万能的,但它是连接模型能力和业务需求最直接的一层。

5、Encoder-Only 和 Decoder-Only 的区别是什么?

Encoder-Only 模型的代表是 BERT,它通过双向自注意力同时看左右文,更适合理解类任务,比如分类、抽取、匹配、检索编码。它常用 MLM 之类的目标训练,本质上偏“编码和表示学习”。

Decoder-Only 模型的代表是 GPT、LLaMA,它使用带 mask 的自注意力,只能看当前位置之前的 token,训练目标通常是 next token prediction。本质上偏“生成和续写”,所以特别适合对话、写作、代码生成和 Agent 执行链路。

从能力上看,Encoder-Only 更擅长把输入压缩成高质量语义表示;Decoder-Only 更擅长基于上下文持续生成。现在大模型应用里,主流聊天模型大多用 Decoder-Only,因为生成能力和扩展性更适合通用助手场景。但在 RAG 系统里,embedding 模型很多还是 Encoder 类结构,因为它们做语义编码更强。

6、你了解大模型评测吗?

大模型评测不能只看“感觉回答不错”,而要分离线评测和线上评测。离线评测看固定测试集上的稳定表现,比如回答正确率、工具调用成功率、检索命中率、幻觉率、拒答准确率、格式稳定性。线上评测则更关注真实业务指标,比如首轮解决率、转人工率、二次追问率、平均时延和 token 成本。

Agent 场景里更重要的是可归因。不能只看最终答案对不对,还要知道是检索错了、重排错了、工具选错了,还是模型生成错了。只有把链路拆开,评测才真正有价值。

7、Attention 结构是什么?

Attention 的核心是让模型在处理当前 token 时,动态关注序列中和它最相关的其他 token,而不是像 RNN 那样只能顺序传递信息。Transformer 里的 Self-Attention 会先把输入映射成 Query、Key、Value 三个矩阵:

然后用 (QKT) 计算相似度,再除以 根号下dk 做缩放,经过 softmax 得到注意力权重,最后对 (V) 加权求和:

多头注意力则是把输入投影到多个不同子空间,每个 head 学习不同关系,最后再拼接起来。

除以根号下dk的原因是防止维度变大后点积数值过大,导致 softmax 过于尖锐、梯度不稳定。Attention 的优势是并行计算能力强,长距离依赖建模更直接,这也是 Transformer 替代传统 RNN 的关键原因之一。

import torch
import torch.nn.functional as F

def attention(Q, K, V):
    d_k = Q.size(-1)
    scores = torch.matmul(Q, K.transpose(-2, -1)) / (d_k ** 0.5)
    weights = F.softmax(scores, dim=-1)
    return torch.matmul(weights, V)

8、上下文记忆架构怎么做?

记忆架构一般分短期记忆、长期记忆和工作记忆。短期记忆保存最近几轮对话,保证多轮上下文连贯;长期记忆保存用户稳定偏好,比如座位偏好、出行城市、酒店偏好、会员身份;工作记忆保存当前任务状态,比如已经查过哪些航班、是否做过改签、上一步工具调用结果是什么。

实际系统里,不会把所有历史聊天原文全塞进 prompt,因为 token 会不断膨胀。更常见的做法是保留最近几轮原文,把更早内容压缩成摘要,再按 query 去召回相关长期记忆。

class MemoryStore:
    def __init__(self):
        self.short_term = []
        self.long_term = {}

    def add_message(self, msg):

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

AI-Agent面试实战专栏 文章被收录于专栏

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

全部评论

相关推荐

评论
点赞
2
分享

创作者周榜

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