快手 AI应用开发 一面

1. 自我介绍

2. 介绍你的实习项目,你做了哪些事情以及你的思考

3. 升级之后 tool 调用准确率提升了多少,怎么衡量

答案:

tool 调用准确率不能只看模型有没有调用工具,而要看调用的工具是否正确、参数是否正确、调用顺序是否正确、结果是否被正确使用。我们会把一次工具调用拆成几个指标:工具选择准确率、参数填充准确率、无效调用率、重复调用率、最终任务成功率。

比如升级前模型经常把“查询保单责任”和“查询历史理赔”混淆,或者漏传 policyId。后来通过工具分域、意图路由、参数 schema 校验和少量高质量样例,工具选择准确率从大概 82% 提升到 92% 左右,关键参数完整率从 88% 提升到 96% 左右。最终不是只看离线集,还要看线上人工审核纠错率有没有下降。

CREATE TABLE tool_call_eval (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    trace_id VARCHAR(64) NOT NULL,
    intent VARCHAR(64) NOT NULL,
    expected_tool VARCHAR(128) NOT NULL,
    actual_tool VARCHAR(128) NOT NULL,
    param_valid TINYINT NOT NULL,
    order_valid TINYINT NOT NULL,
    final_success TINYINT NOT NULL,
    created_at DATETIME NOT NULL
);

评估时按 trace 聚合:

SELECT
    COUNT(*) AS total,
    SUM(expected_tool = actual_tool) / COUNT(*) AS tool_accuracy,
    SUM(param_valid) / COUNT(*) AS param_accuracy,
    SUM(final_success) / COUNT(*) AS task_success_rate
FROM tool_call_eval
WHERE created_at >= '2026-05-01';

4. 为什么考虑做成 Skill 流程,而不是普通 Workflow

答案:

Workflow 更像固定流程,适合步骤稳定、分支明确的任务,比如“提交理赔申请 -> 校验材料 -> 人工审核 -> 打款”。Skill 更像可复用能力,适合被不同 Agent、不同流程按需调用,比如“解析发票”“匹配医保目录”“生成拒赔解释”“压缩会话记忆”。

在理赔场景里,如果所有东西都做成 Workflow,会导致流程越来越多、重复节点很多,而且难以组合。比如门诊理赔、住院理赔、药品理赔都需要“药品目录匹配”能力,这个能力就应该沉淀成 Skill,而不是每个 workflow 里复制一份。

Workflow:面向业务流程,强调顺序、状态、审批、重试
Skill:面向能力复用,强调输入输出、可组合、可编排

Skill 的定义会更像一个稳定接口:

{
  "skillName": "medical_catalog_match",
  "input": {
    "drugName": "string",
    "diagnosisCode": "string",
    "hospitalLevel": "string"
  },
  "output": {
    "covered": "boolean",
    "matchedRuleId": "string",
    "reason": "string"
  }
}

5. 你怎么理解 Skill,它和 Tool、Agent 的区别是什么

答案:

Tool 是最底层的可调用动作,比如查数据库、查知识库、调用 OCR、查询保单。Skill 是对一组工具和逻辑的封装,它有明确业务语义,比如“判断药品是否可赔”“生成理赔材料缺失说明”。Agent 则是具备任务理解、计划和协调能力的执行主体。

举个例子,query_policy 是 Tool,claim_liability_check 是 Skill,ClaimAuditAgent 是 Agent。Agent 可以调用多个 Skill,Skill 内部可以调用多个 Tool。这样分层后,工具不会直接暴露给模型太多,复杂能力也能复用。

Agent:负责理解任务、制定计划、协调执行
Skill:负责完成一个稳定业务能力
Tool:负责执行一个确定性动作

Java 中可以这样抽象:

public interface Skill<I, O> {
    String name();
    O execute(I input, SkillContext context);
}

public class LiabilityCheckSkill implements Skill<LiabilityInput, LiabilityOutput> {
    @Override
    public String name() {
        return "liability_check";
    }

    @Override
    public LiabilityOutput execute(LiabilityInput input, SkillContext context) {
        Policy policy = context.policyTool().queryPolicy(input.policyId());
        RuleResult rule = context.ruleTool().match(policy, input.diagnosisCode());
        return LiabilityOutput.from(rule);
    }
}

6. 除了 RAG 长期记忆,有没有做用户偏好类记忆,压缩后的 token 大概多大

答案:

有做,但不会把所有历史对话都存成长期记忆。长期记忆分两类,一类是事实记忆,比如用户常用保单、家庭成员关系、常见就诊城市;另一类是偏好记忆,比如用户希望解释更口语化、是否需要展示详细条款、是否偏好短信通知。模型临时总结出来的猜测不能直接写入长期记忆,必须有明确行为或用户确认。

记忆压缩后一般控制在几百 token 到一千 token 以内,核心是“可用”而不是“完整”。如果一个用户的历史对话很多,会按稳定程度、更新时间、业务相关性排序,只取当前任务需要的部分。

{
  "userMemory": {
    "defaultPolicyId": "P****123",
    "frequentClaimType": "outpatient",
    "preferredExplainStyle": "simple",
    "familyMembers": [
      {"relation": "child", "maskedId": "U****88"}
    ]
  }
}

记忆读取时会按场景裁剪:

public UserMemoryView buildMemoryView(String userId, ClaimScene scene) {
    UserMemory memory = memoryRepo.findByUserId(userId);
    return UserMemoryView.builder()
            .defaultPolicyId(memory.getDefaultPolicyId())
            .preferredExplainStyle(memory.getPreferredExplainStyle())
            .recentClaimType(memory.getRecentClaimType(scene))
            .build();
}

7. 产品的用户量、每日 token 使用量、底层模型怎么估算

答案:

这类问题不能只报一个数字,要能说清估算方式。假设日活 5 万,20% 用户会触发 AI 审核或解释,也就是 1 万次 AI 会话;每次会话平均 3 轮,每轮输入上下文 1500 token,输出 500 token,那么每天大概是:

1 万会话 * 3 轮 * (1500 输入 + 500 输出) = 6000 万 token / 天

底层模型不会只用一个。简单意图识别、关键词抽取、格式修复可以用小模型;复杂理赔解释、条款归因、多证据综合用大模型;RAG embedding 用专门的 embedding 模型。这样可以控制成本和延迟。

小模型:意图识别、槽位抽取、JSON 修复
大模型:复杂解释、多证据综合、争议场景总结
Embedding 模型:知识库向量化
Rerank 模型:召回结果重排

如果 P95 延迟要求严格,还要做模型路由和降级:大模型超时后返回模板化解释或进入人工审核队列。

8. 用户在线反馈怎么做,不同模型和提示词的 AB 测试如何体现效果

答案:

在线反馈会分显式反馈和隐式反馈。显式反馈是用户点“有帮助 / 没帮助”、客服标记“可直接发送 / 需要修改”;隐式反馈是用户是否继续追问、客服修改比例、理赔工单是否被退回、人工复核是否改判。

AB 测试时不能只看点赞率。理赔场景更关注准确性和风险,所以会看证据引用率、人工修改率、投诉率、审核耗时、最终改判率。不同模型和 prompt 要随机分流,但要保证同一用户或同一工单稳定落到同一实验组,避免体验混乱。

CREATE TABLE llm_ab_eval (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    request_id VARCHAR(64),
    user_id VARCHAR(64),
    experiment_key VARCHAR(64),
    group_name VARCHAR(32),
    model_name VARCHAR(64),
    prompt_version VARCHAR(64),
    helpful TINYINT,
    manual_edit_rate DECIMAL(6,4),
    evidence_valid TINYINT,
    created_at DATETIME
);

分流可以这样做:

public String assignGroup(String userId, String experimentKey) {
    int hash = Math.abs(Objects.hash(userId, experimentKey));
    return hash % 100 < 50 ? "A" : "B";
}

9. 讲一下你的 Agent Runtime 设计

答案:

Agent Runtime 我会拆成 Request Layer、Planner、Tool Router、Executor、Memory Manager、Context Builder、Verifier、Trace Logger。请求进来后先做鉴权和意图识别,再构建上下文,然后由 Planner 生成计划。计划不会直接执行,要经过权限、预算、工具白名单和依赖关系校验。Executor 负责真正执行工具,最后 Verifier 校验模型输出是否合规。

Runtime 的关键是把模型的不确定性控制在边界内。比如模型可以建议调用哪个 Skill,但不能越权访问用户保单;模型可以生成解释,但不能编造赔付结论;模型可以要求补充材料,但必须来自规则命中结果。

Request
  -> Auth / RateLimit
  -> Intent Router
  -> Memory Manager
  -> Context Builder
  -> Planner
  -> Plan Verifier
  -> Tool / Skill Executor
  -> Evidence Merger
  -> LLM Generator
  -> Output Verifier
  -> Trace Log

计划结构示例:

{
  "intent": "claim_audit",
  "steps": [
    {"id": "s1", "skill": "policy_liability_check"},
    {"id": "s2", "skill": "medical_catalog_match"},
    {"id": "s3", "skill": "claim_explanation_generate"}
  ]
}

10. Agent Runtime 中上下文爆炸怎么处理

答案:

上下文爆炸一般来自历史对话、工具结果、RAG 文档、用户材料和系统提示词都不断累积。解决方式是分层压缩和预算控制。每次请求进入模型前,要先定义 token budget,比如 system prompt 800,用户问题 500,历史摘要 1000,工具证据 2000,RAG 文档 2000。

历史对话不直接全量塞入,而是压缩成任务状态和用户偏好;工具结果不塞完整 JSON,而是提取证据字段;RAG 文档只保留 topK 片段;低价值上下文直接丢弃。对于超长任务,分阶段调用模型,每阶段只处理局部上下文。

public class ContextBudget {
    int systemTokens = 800;
    int userTokens = 500;
    int memoryTokens = 800;
    int evidenceTokens = 2000;
    int ragTokens = 2000;
}

证据压缩示例:

public EvidenceView compress(ClaimToolResult result) {
    return new EvidenceView(
            result.getEvidenceId(),
            result.getSource(),
            result.getKeyConclusion(),
            result.getRuleId()
    );
}

11. Agent 循环调用、重复调用怎么处理

答案:

Agent 循环调用通常是模型没有得到满意结果,反复调用同一个工具,或者工具结果为空后不断换参数试探。生产里不能让这种情况发生,必须在 Runtime 层加 harness。常见限制包括最大调用轮数、最大工具调用次数、相同工具相同参数只允许调用一次、工具失败后按错误类型决定是否重试。

还要记录工具调用指纹,用工具名和参数 hash 判断重复。如果模型连续两次计划没有产生新信息,就终止并返回“需要补充信息”或转人工。

public class ToolCallGuard {
    private final Set<String> fingerprints = new HashSet<>();
    private final int maxCalls;

    public ToolCallGuard(int maxCalls) {
        this.maxCalls = maxCalls;
    }

    public void check(String toolName, String argsJson) {
        if (fingerprints.size() >= maxCalls) {
            throw new RuntimeException("TOOL_CALL_LIMIT_EXCEEDED");
        }

        String fp = toolName + ":" + DigestUtils.md5Dig

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

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

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

全部评论

相关推荐

昨天 15:26
北京邮电大学 C++
回家当保安:今天刚过字节一面,接佬的好运
我的求职进度条
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
昨天 11:06
兄弟们,我可能下周就要分手了。但我现在还没分。我们俩上周末还约了去吃她最爱那家麻辣烫。然后我大概率会在某一天,找一个不太对的时机,说出那句话。我先把背景交代清楚,佬们帮我看看。我们大三在一起的,到现在两年零三个月。今年春招我冲进了字节,base&nbsp;北京,我读的某&nbsp;211&nbsp;末流,秋招挂得一塌糊涂,春招最后一波临门一脚才进去的,寝室那天给我开了瓶酒。她比较稳,去年寒假就开始准备公考,四月份压线进了面试,五月初公示,老家市直编制内,到手&nbsp;6k。三方是上周一签的。我自己一个人去的打印店。她周三签的,她爸妈一起陪她去的人社局,她朋友圈发了一张她爸跟她的合照,配文"以后能天天回家吃饭了"。那张图我看了大概十遍。签完那天晚上我们视频,我在公司加班,背景全是工位的灯,我啃着一个鸡蛋灌饼跟她汇报今天&nbsp;mentor&nbsp;怎么&nbsp;push&nbsp;我。她"嗯嗯"了二十分钟。挂了电话以后我盯着天花板看了很久。我突然意识到一件事:从签三方那天起,我们之间多了一个谁都没说出口的东西——不是异地,是节奏。我往后五年是&nbsp;KPI、OKR、晋升。她往后五年是科室、年度考核、社保公积金、相亲对象的家长(如果我们分了的话)。我们俩从今往后讨论的世界,已经不是同一个了。牛客有个老哥说"异地恋最怕的不是距离,是你发现你们俩聊天没东西可聊了"。我现在还没到那一步,但我能感觉到——我跟她说我被&nbsp;leader&nbsp;夸了,她除了"哇好棒"实在不知道还能说什么。她跟我说她们科里那个姐姐二胎了,我"嗯"了一下。我看了一周的"异地恋怎么撑过第一年"。也看了一周的"毕业季分手怎么不留遗憾"。两个标签的帖子我都点了赞。我也试着算过。北京到她家高铁五个小时,单程二等座&nbsp;553。我周五加班到十一点根本赶不上末班车,只能周六早上飞回去周日晚上飞回来,一趟来回&nbsp;2000&nbsp;多,我一个月顶多去两次。钱不是问题。问题是我很大概率没时间去。字节应届生的周末是被切到分钟的。两天里有一天还在改文档,剩下那天用来洗澡补眠看医生。飞回去这件事,听起来是体力问题,本质是"我每周剩下的那点产能能不能匀给她"——我现在的诚实答案是:基本匀不出来。但这些都不是最难的事。最难的是我没办法跟她说"你别考公了你来北京",因为她爸妈刚把家里那间小屋给她收拾出来当书房;我也没办法跟我妈说"我把字节退了回老家"——我爸去年失业了,这个&nbsp;offer&nbsp;是我们家三口人的指望。我们俩都太懂事了。懂事到不敢提任何会让对方为难的方案。但越懂事,越不知道怎么开口提分手。我现在每天通勤的地铁上都在打腹稿。我想过几个版本:-&nbsp;版本&nbsp;A:"我们都没错,只是路不一样了,散了吧。"——太冷了,她会哭。-&nbsp;版本&nbsp;B:"你先回家吧,半年后我们再看。"——骗她也骗我自己。半年后只会更难开口。-&nbsp;版本&nbsp;C:"对不起,是我不够爱你。"——谎话,但是最干净的谎话。我现在卡在&nbsp;A&nbsp;和&nbsp;B&nbsp;之间。所以我也没什么结论。我只是想问问已经毕业过、已经经历过这一关的佬们:你们当年是谁先开口的?如果重来一次,你会不会选"先试半年"这个看似温柔实则慢性折磨的方案?如果"懂事"是分手的最大障碍,那应该怎么破?下周我大概率会在周末,和她再吃一顿麻辣烫,出门走两步的时候说。为了防止熟人认出,还是匿了
牛客75339618...:分手拜拜就行了,你们双方都没有把对方考虑进去自己的后面计划,真正的考虑应该是她考一个二线城市的编制,你去二线城市的互联网,既然双方一开始都没有考虑对方(你对象考公考老家,你去北京也没考虑你对象能不能北京找到工作),那就分手完事了呗,这还有啥好说的,难不成异地恋拖着,你觉得可能吗
记录我的毕业季
点赞 评论 收藏
分享
xdm&nbsp;早上喝奶茶差点喷出来。事情是这样的,我们班有个哥们儿,简称&nbsp;L,去年秋招拿了字节sp,专业方向是后端。我们当时都震惊:这哥们儿平时课上从来不发言,期末小组作业基本是划水的那种,刷题平台&nbsp;commit记录我点进去看过,绿格子稀稀拉拉。但他面试一路绿灯。一面二面三面&nbsp;hr&nbsp;面,全过,给的还是sp。当时班级群里恭喜他的、问他经验的、约饭的,热闹了一周。他说自己"运气好,准备充分"。我们都信了,直到三月初他入职。入职第二周开始,班里另一个进字节的同学W(在隔壁组的)开始跟我他的不对劲。一开始是写代码慢,后来写不出来,再后来是组里&nbsp;mentor&nbsp;让他fix&nbsp;一个简单&nbsp;bug&nbsp;都搞了一下午没动静。最离谱的是上周。W&nbsp;说他们大部门搞了个新人分享会,让新人讲一下自己负责模块的设计思路。L&nbsp;上去讲了&nbsp;20分钟,全程念稿子,问答环节别人随便问一个"那你这里为什么用&nbsp;Redis&nbsp;不用&nbsp;Memcached",他直接卡&nbsp;30秒说"这个我回去再确认一下"。会后他&nbsp;mentor&nbsp;直接找&nbsp;leader&nbsp;谈,leader&nbsp;找&nbsp;hr&nbsp;谈,hr调出了他面试录像,全程对比口型和回答节奏,发现他二三面有大量时长在偷偷看屏幕外(推测开了双机位&nbsp;AI&nbsp;答题)。(这段是&nbsp;W后来转述给我的,他自己也是听他组里同事八卦来的)昨天下班前,W&nbsp;告诉我L&nbsp;被辞退了,让他自己走,不走就走仲裁但会发函到学校。L&nbsp;现在已经回学校了,朋友圈仅三天可见。我说真的,我不是个心眼小的人,但是我看到这个消息的时候真的有种"嗯,挺好"的感觉。去年秋招我投字节后端,简历挂。我准备了八个月,背&nbsp;八股&nbsp;+&nbsp;刷&nbsp;500&nbsp;题&nbsp;+项目改了三版,连面试机会都没拿到。班里这哥们儿凭着一个外挂上岸,最后还是被甩出来了。不是说作弊就一定会被发现,但是当面试拿到的&nbsp;offer远远超出真实能力的时候,迟早会有这一天。试用期三个月不是给你过家家的,是真的要写代码、要在会议上回答问题、要扛需求的。我现在反而有点同情他。同情他相信"上岸就是终点"。发出来不是为了嘲笑谁,就是想说给那些正在被身边作弊上岸的同学搞得很&nbsp;emo&nbsp;的&nbsp;uu&nbsp;们听——别急,回旋镖很长,但它一定会回来。你继续刷你的题,写你的项目,背你的八股。该是你的迟早是你的,不是你的早晚还得还回去。xdm&nbsp;共勉。
牛客12588360...:我不想评论面试方式,作弊是绝对不对的,但是你八股加刷题也不过是个做题小子,他穿帮纯粹是他菜,你也没有高明到哪里去
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

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