深信服 AI应用开发 一面

1. 自我介绍

2. 你在项目里主要负责哪一块,核心难点是什么

3. 意图识别具体怎么做,哪些意图是你们自己定义的

答案:

意图不是模型自己随便生成的,而是业务先定义好可执行的意图集合。比如在商家经营诊断里,会定义订单转化分析、差评归因、客服质检、活动效果复盘、规则咨询、商品套餐优化、竞品对比、经营日报生成这些意图。每个意图都对应明确的输入、需要的工具和输出格式。

实现上会用规则加模型混合。像门店 ID、活动 ID、订单号这种强结构化字段先用规则抽取;再用模型做意图分类和槽位补全。模型输出不能直接信任,要校验意图是否在白名单内、槽位是否合法、是否缺关键参数。如果缺门店或时间范围,就进入追问,而不是直接查全量数据。

{
  "intent": "store_conversion_diagnosis",
  "slots": {
    "storeId": "S10086",
    "timeRange": "last_7_days",
    "metric": "visit_to_order_rate"
  },
  "needClarify": false,
  "confidence": 0.91
}
var allowedIntents = map[string]bool{
    "store_conversion_diagnosis": true,
    "review_reason_analysis":     true,
    "campaign_effect_review":     true,
    "policy_consulting":          true,
}

func ValidateIntent(intent string) bool {
    return allowedIntents[intent]
}

4. 意图里的槽位抽取怎么保证准确,不让模型乱填

答案:

槽位抽取不能只靠模型生成文本。项目里会把槽位分成强校验槽位和弱语义槽位。强校验槽位比如门店 ID、活动 ID、订单 ID、日期范围,必须通过正则、字典、数据库或权限系统校验。弱语义槽位比如“最近”“转化不好”“客诉严重”,可以让模型归一化成标准字段。

比如用户说“看下上周望京店团购券效果”,模型抽到门店名后,还要去门店系统查这个用户是否有权限访问该门店,并把“上周”转换成具体日期。模型不能自己编一个 storeId。

type SlotResult struct {
    StoreID    string `json:"storeId"`
    StoreName  string `json:"storeName"`
    StartDate  string `json:"startDate"`
    EndDate    string `json:"endDate"`
    Metric     string `json:"metric"`
    NeedVerify bool   `json:"needVerify"`
}

func VerifyStore(ctx context.Context, userID, storeName string) (string, error) {
    store, err := storeRepo.FindByNameAndUser(ctx, userID, storeName)
    if err != nil {
        return "", err
    }
    if store == nil {
        return "", fmt.Errorf("store not found or no permission")
    }
    return store.ID, nil
}

5. 你们的工作流引擎体现在哪里,为什么不用一段代码硬写流程

答案:

工作流引擎主要用来承载多步骤、多分支、可重试、可观测的 Agent 执行链路。如果用一段代码硬写流程,短期可以跑,但后面新增意图、插入校验、调整工具顺序、做灰度实验都会很痛苦。工作流引擎能把每个步骤抽成节点,节点之间通过状态和上下文传递数据。

比如“活动效果复盘”这个 workflow 会先查活动配置,再查曝光点击,再查订单转化,再查用户评价,最后生成结论。其中指标查询和评价分析可以并行,结果汇总后再调用模型。用 workflow 可以明确哪些节点失败可降级,哪些失败必须终止。

workflow: campaign_review
steps:
  - id: load_campaign
    type: tool
    tool: query_campaign_config
  - id: query_metrics
    type: tool
    tool: query_campaign_metrics
    dependsOn: [load_campaign]
  - id: analyze_reviews
    type: tool
    tool: analyze_review_sentiment
    dependsOn: [load_campaign]
  - id: generate_report
    type: llm
    dependsOn: [query_metrics, analyze_reviews]

6. LangChain4j 在项目里用到了哪些能力

答案:

LangChain4j 主要用在 Java 服务里的模型调用封装、prompt 模板、chat memory、tool calling、RAG 检索和输出解析。它的好处是把模型客户端、embedding、向量库、工具调用这些能力抽象得比较统一,业务代码不用直接散落很多 HTTP 调用。

但生产里不能完全依赖框架默认能力。比如工具调用要接入自己的权限、审计、超时和限流;memory 也不能无限保存;RAG 检索需要结合业务元数据过滤。LangChain4j 更像基础组件,外层还要包一层企业自己的 Agent Runtime。

AiServices.builder(StoreAgent.class)
        .chatLanguageModel(chatModel)
        .chatMemory(chatMemory)
        .tools(storeMetricTool, reviewTool, campaignTool)
        .build();
public interface StoreAgent {
    @SystemMessage("你是商家经营分析助手,必须基于工具和证据回答。")
    String diagnose(@UserMessage String question);
}

7. Agent 是怎么编排的,Planner、Executor、Verifier 怎么分工

答案:

Agent 编排里我会拆成 Planner、Executor、Verifier。Planner 负责根据意图和上下文生成执行计划,但它只能在允许的工具和 workflow 中选择。Executor 负责真正调用工具、处理超时、重试和结果合并。Verifier 负责检查最终答案是否符合结构、是否引用证据、是否越权、是否和工具结果冲突。

这种拆分比让模型一口气从输入答到输出稳定很多。Planner 可以用模型辅助,但 Executor 和 Verifier 要尽量确定性。尤其是高风险动作,比如修改活动预算、发送商家通知,不能只靠模型判断,必须有权限和二次确认。

type PlanStep struct {
    ID        string   `json:"id"`
    Tool      string   `json:"tool"`
    DependsOn []string `json:"dependsOn"`
    Critical  bool     `json:"critical"`
}

type AgentPlan struct {
    Intent string     `json:"intent"`
    Steps  []PlanStep `json:"steps"`
}

8. ReAct 会存在什么问题,为什么工具调用容易死循环

答案:

ReAct 的问题是模型会在“思考—调用工具—观察结果”之间循环,如果没有外部约束,容易出现重复调用同一个工具、换参数反复试探、工具失败后继续猜、甚至把工具返回中的文本当作新指令。它适合探索性任务,但在生产系统里风险很高。

解决方式不是完全不用 ReAct,而是加边界。比如限制最大轮数、最大工具调用次数、相同工具相同参数只能调用一次、工具失败后不能无脑重试、关键工具失败必须终止。还要把工具选择限定在当前意图允许的集合里,不能让模型看到所有工具。

func CheckToolLoop(history []ToolCall, next ToolCall) error {
    fp := next.Name + ":" + HashJSON(next.Args)
    for _, h := range history {
        if h.Name+":"+HashJSON(h.Args) == fp {
            return fmt.Errorf("duplicated tool call: %s", next.Name)
        }
    }
    if len(history) >= 8 {
        return fmt.Errorf("tool call limit exceeded")
    }
    return nil
}

9. 除了限制工具调用次数,还有什么办法让 ReAct 更稳定

答案:

更稳定的办法是把自由 ReAct 改成“候选计划 + 受控执行”。模型可以给出计划,但计划必须经过规则校验。比如每个意图只允许某些工具,工具之间有依赖关系,某些工具必须先执行,某些工具可以并行。这样模型不是边想边乱调,而是在一个受限图里选择路径。

还可以把复杂任务拆成子任务。比如差评归因先做情感分类,再做主题聚类,再查订单和客服会话,最后总结。每个子任务有明确输入输出,模型只处理局部推理。这样比一个大 prompt 让模型自己规划完整流程更可控。

{
  "allowedTools": [
    "query_store_metrics",
    "query_review_samples",
    "cluster_review_topics",
    "generate_reason_summary"
  ],
  "mustBefore": {
    "cluster_review_topics": ["query_review_samples"],
    "generate_reason_summary": ["query_store_metrics", "cluster_review_topics"]
  }
}

10. CoT 能不能直接展示给用户,生产里怎么处理推理过程

答案:

生产里不应该直接把模型的完整思考链展示给用户。完整 CoT 可能包含不稳定推理、错误假设、敏感上下文、内部工具信息。用户真正需要的是可解释结论,而不是模型的全部草稿思考。

更合适的是输出“可验证推理摘要”。比如把依据拆成指标变化、证据片段、规则引用、结论和建议。内部可以让模型做 reasoning,但外部只展示经过整理的解释。对于高风险场景,还要让结论和证据一一对应,避免看起来解释很多但没有证据支持。

{
  "conclusion": "近 7 天到店转化下降主要与优惠券核销率下降有关",
  "evidence": [
    "优惠券领取到核销率从 18.2% 下降到 11.4%",
    "差评中 32% 提到套餐可用时段限制"
  ],
  "suggestion": "建议放宽套餐可用时段,并在详情页前置说明限制"
}

11. 如何保证模型最终输出结构不要变

答案:

不能只靠提示词要求“请输出 JSON”。模型在复杂上下文里可能多输出解释、字段缺失、类型错误。所以要做三层控制:第一层 prompt 明确 schema,第二层使用模型的结构化输出能力或 function schema,第三层后端做 JSON 解析和字段校验。如果解析失败,可以触发一次修复重试,但不能无限修复。

对于关键接口,最终响应最好由后端组装。模型只生成部分字段,比如原因摘要和建议,指标、证据、引用来源由后端确定性填充。这样能降低模型把结构改乱的概率。

type DiagnosisOutput struct {
    Conclusion string   `json:"conclusion" validate:"required"`
    Evidence   []string `json:"evidence" validate:"required,min=1"`
    Suggestion string   `json:"suggestion" validate:"required"`
    Confidence float64  `json:"confidence" validate:"gte=0,lte=1"`
}

func ParseOutput(raw string) (*DiagnosisOutput, error) {
    var out DiagnosisOutput
    if err := json.Unmarshal([]byte(raw), &out); err != nil {
        return nil, err
    }
    if out.Confidence < 0 || out.Confidence > 1 {
        return nil, fmt.Errorf("invalid confidence")
    }
    return &out, nil
}

12. 模型调用会不会出现幻觉,怎么防止模型拿训练知识回答业务数据

答案:

会出现。尤其是用户问“这个门店为什么下降”“这个活动是不是有效”时,如果工具没有查到数据,模型可能根据常识编出原因。防止方式是把内部数据问题和通用知识问题严格分开。凡是涉及门店、订单、活动、评价、客服、配置的数据问题,必须先调用工具或检索证据,没有证据就拒

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

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

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

全部评论

相关推荐

05-09 15:06
湘南学院 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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