V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dongcxcx
V2EX  ›  问与答

在实践过程中,用大模型做一个需求遇到的问题

  •  
  •   dongcxcx · 52 天前 · 2011 次点击
    这是一个创建于 52 天前的主题,其中的信息可能已经有所发展或是发生改变。

    以下是我尝试分别用 langchain, langgraph,以及 ReAct 的三次实验,请大家帮忙看看有没有更好的解决方案,多谢。整体排版让 ai 给我优化了一下

    售前报价客服的需求与技术演进

    需求概述

    用户提出一个报价问题,例如:

    iphone16pro max, 128g, 黑色 多少钱?

    实际 SKU 要复杂得多,但不影响核心流程:

    1. 大模型解析用户语义中的产品名;
    2. 我根据产品名从数据库中查询 SKU 信息;
    3. 拿到完整 SKU 后计算价格。

    技术尝试过程

    第一次尝试:LangChain4j + Prompt

    我在 prompt 中指定了多个 function call:

    1. 解析产品名
    2. 根据产品名获取 SKU 信息
    3. 根据完整 SKU 信息计算价格
    4. 如果缺失必要的字段,向用户确认

    实际效果: 不理想,属于 demo 偶尔能跑通,但经常出问题:

    • 大模型直接跳过第一步,调用第二步方法;
    • 有时甚至直接输出“好的,正在为你计算价格”,并未执行任何函数调用;
    • 缺乏可控性。

    第二次尝试:LangGraph

    尝试用流程图方式替代 prompt 中的 if-else 指令:

    • 显式建模产品识别 → 获取 SKU → 补齐字段 → 计算价格等步骤;
    • 理论上更可控。

    实际效果: 依然不稳定,部分场景下流程刚性,模型无法灵活应对用户输入的变化。


    第三次尝试:ReAct 框架

    在 prompt 中使用 ReAct 框架( Thought → Action → Observation ):

    • 将“决策权”交还给大模型;
    • 允许其自行判断调用哪些工具;
    • 相比直接写死顺序,逻辑更灵活。

    实际效果:

    • 看起来更聪明,但问题依旧存在;
    • 可能跳过某些关键步骤;
    • 经常需要靠“缝缝补补”的方式不断优化 prompt ;
    • 仍然不确定是否能彻底杜绝不可控行为。

    总结

    无论是 prompt + function call 、LangGraph 流程图,还是 ReAct 框架,核心问题始终是:
    大模型行为的不可控性,尤其是在多步骤流程中容易出错或跳步,目前仍未找到完全可靠的解决方案。

    第 1 条附言  ·  52 天前
    这是我的 prompt
    ============================

    你是一名 XX 报价助手,你的任务是理解用户的自然语言需求,并使用以下工具完成产品识别、字段补全和价格计算。

    你只能通过调用工具与用户交互,不能直接对话或输出答案。每一步都必须按如下格式输出:

    Thought: 你对用户输入的分析与推理
    Action: 工具名称(如下列表之一)
    Action Input: 工具的 JSON 格式参数

    ---

    ❗ [重要规则] :

    - 每次调用工具前,你都必须先输出 Thought 、Action 和 Action Input 。
    - 即使你已经明确要调用工具,也必须先写出你的分析过程,不可省略。
    - 调用工具时,只能使用结构化的工具调用(即 tool_call ),不能仅用文字模拟调用。
    - 当你调用 askUser 工具后,**必须立即结束本轮回复,等待用户答复**
    - 在未收到用户答复前,**不得进行任何进一步的思考或工具调用**
    - 你不能假设用户已经回答。你必须等用户真实输入后再继续推理。

    ---

    可用工具如下:

    1. identifyProductType(userInput: string)
    - 用于识别用户输入中提到的产品类型(如 xx 等)
    - 如果无法判断,请返回 "未知",并使用 askUser 工具向用户提问
    - 输入格式:{ "userInput": "我想做一些 xx" }

    2. parseSku(productType: string)
    - 用于查询指定产品类型需要填写的字段(如尺寸、工艺等)
    - 输入格式:{ "productType": "xx" }

    3. askUser(question: string)
    - 用于向用户提问缺失字段信息。你只能通过调用该工具进行提问,不能自己输出问题
    - 输入格式:{ "question": "请问您需要的材质是什么?" }
    - ⚠️ 调用后必须结束本轮回复

    4. getPrice(product: string, quantity: number, fields: dict)
    - 用于计算最终报价。仅当用户已补全所有字段时调用
    - 输入格式:
    {
    "product": "xx",
    "quantity": 500,
    "fields": {
    "材质": "x",
    "尺寸": "xx",
    }
    }

    5. getAllSupportedProductTypes()
    - 获取目前系统中支持的所有产品类型
    - 输入格式:{}
    - 返回值:["xx", "xx1", "xx2"]

    ---

    [使用示例]

    用户输入:「我想做一些 xx 」

    Thought: 用户提到“xx”但没有明确产品类型,我需要识别它对应的标准产品
    Action: identifyProductType
    Action Input: { "userInput": "我想做一些 xx" }

    (假设返回结果:"xx")

    Thought: 确定产品类型为 xx ,下一步是查询其字段结构
    Action: parseSku
    Action Input: { "productType": "xx" }

    (假设返回字段有 材质、尺寸、数量)

    Thought: 用户已提供数量,但缺少材质和尺寸
    Action: askUser
    Action Input: { "question": "请问您希望使用什么材质和尺寸?" }

    ❗此处应立即结束推理,等待用户回答

    (假设用户真实回复:xxx )

    Thought: 字段已齐全,可以计算价格
    Action: getPrice
    Action Input:
    {
    "product": "xx",
    "quantity": 500,
    "fields": {
    "材质": "xx",
    "尺寸": "xx",
    }
    }
    21 条回复    2025-07-29 11:36:13 +08:00
    geebos
        1
    geebos  
    PRO
       52 天前   ❤️ 1
    固定流程可以不依赖 AI 调用,直接指定第一步的 AI 提取产品名称,拿到输出调接口查数据再给第二步的 AI
    lanweizhujiao
        2
    lanweizhujiao  
       52 天前   ❤️ 1
    1 楼说的对,
    NoDataNoBB
        3
    NoDataNoBB  
       52 天前   ❤️ 1
    可以试试 json mode
    Mzs
        4
    Mzs  
       52 天前
    固定流程用 dify 或者扣子
    maolon
        5
    maolon  
       52 天前 via Android   ❤️ 2
    你这最关键的用了哪个模型驱动都不说
    每个 agent 对各种 prompt 的效果也不一致,
    你怎么设计的 prompt 也要描述清楚,
    最后才是这些框架 workflow 的问题
    huangrong
        6
    huangrong  
       52 天前   ❤️ 1
    我目前是通过将最小化大模型的流程,但也只能减少出错概率
    huangrong
        7
    huangrong  
       52 天前
    @huangrong 多了个将
    dongcxcx
        8
    dongcxcx  
    OP
       52 天前
    @maolon 大佬,prompt 已 append 。我使用的是 gpt-4o, gpt-4o-mini, 以及 Deepseek-v3, 差别并不大。 都会有一样的问题
    @huangrong 最小化是什么意思,主要人工控制流程?
    @Mzs 谢谢,我研究下
    maolon
        9
    maolon  
       52 天前
    @dongcxcx prompt 看着没啥问题,那一般这种问题解决方法就是
    1. langgraph 做一个前置检查 node (在这个 node 里判断用户信息是否完整,不完整就直接去 respond node 向用户要信息)
    2. 如果保险起见就再做一个后置检查,去读你的 messages 记录里的 function call 是否有成功调用 sku 查询
    3. prompt 里加入详细的流程例子做引导
    4. 如果效果还是不好,在前置 node 里做用户 query 标准化转写
    5. 最后不要用 4o-mini ,性能太弱,不要用 dsv3 ,指令遵循不行,虽然以我的经验来看 4o 实际不适合 react 的场景,如果可能可以酌情使用更好的模型(带 thinking/混合 thinking 模式),不行就算了
    litchinn
        10
    litchinn  
       52 天前
    可以试试一楼的,分阶段做
    huangrong
        11
    huangrong  
       52 天前
    @dongcxcx 首先你可以让 AI 帮你改改 prompt ,看看有没有可改进的地方,主要是给他提使用现有 prompt 可能恢复发生的问题,让他尽量完善 prompt 。
    我目前没在流程中让 AI 调用工具。我现在的流程主要还是通过代码来约束。
    比如按照你的流程,我会先让 AI 进行产品识别,通过分类等维度使用代码确认产品类别是否存在,如果不存在则重复。此时 AI 的能力仅仅是提供产品类别或者是在商品列表中选出最有可能的商品,出错的概率会稍微小一些。
    dongcxcx
        12
    dongcxcx  
    OP
       52 天前 via iPhone
    1.我当时用 langgraph 去做,确实是这样的。最前面是一个意图识别节点。判断用户是初次报价,继续报价,还是乱七八糟的问题,也不是 100% 正确。加上太多的 if-else 判断,让我感觉是全靠我在控制流程,ai 起到的作用仅仅是识别自然语言,提取字段的作用。就被我放弃了。
    @maolon 我再试试其他模型试试
    dongcxcx
        13
    dongcxcx  
    OP
       52 天前 via iPhone
    另外,有没有推荐的模型。谢谢🙏@maolon
    maolon
        14
    maolon  
       52 天前
    @dongcxcx #12 kimi k2 试下?
    我的意思不是用前置 node 判断用户意图(意图识别在模型性能不够强的情况下非常容易出错),而是简单判断信息是否完整,相当于做一次前置过滤,将用户问题按标准化格式转写也是一种方法
    Clannad0708
        15
    Clannad0708  
       52 天前
    你的 function 里面的 description 要写的清楚,建议构建一个购物的流程体系,比如给 function 打上标签,前期中期后期,通过标签调用控制试试
    iyaozhen
        16
    iyaozhen  
       52 天前
    感觉你的思路有点问题

    你的工具也很很奇怪,而且工具带有流程 “如果无法判断,请返回 "未知",并使用 askUser 工具向用户提问” “调用后必须结束本轮回复” 没见过这么写的
    “ 每次调用工具前,你都必须先输出 Thought 、Action 和 Action Input ” 这些框架都做了吧,不需要你自己写。“ [重要规则] ”里面的每一条都很奇怪

    “用于计算最终报价。仅当用户已补全所有字段时调用” 这样写也不对,你哪些字段必填,function call 声明好就行。

    而且你不要想一步解决,当然不是说模型做不到,而是你的思路要清晰。
    就像 1 楼说的分步骤。

    第一步就是需求澄清:基本上是个 ReAct 过程,只给一个函数,query sku ,连通数据库做确定性的查询,让大模型不断解析用户语义,做查询,比如用户说的是 iphone16 pm ,让大模型能转换 query 变成 iphone16 pro max 去查 sku
    差不出来,你自己流程控制,再去让用户说清楚点

    查询出来后可能多个 sku ,给用户总结说明下就差不多了吧
    raydied
        17
    raydied  
       52 天前
    如果是固定流程的话,为什么不是有多个选择器呢?
    你的场景属于高固定场景,类似我之前的一个场景,AI+系统——主打语音助手。

    个人感觉还用不到 lang-graph 、以及 moe+too-luse 的模式。

    我们当时的做法是 slot+固定 function 调用。
    - 通过 chatgpt4o-mini 的微调,按照模板,大概列一下目标场景和预期的 slot 模板,
    - 调用固定 function
    ---
    如果是多 function ,才需要用到模型的 function-call 功能。此时,也需要尽量高度抽象你的 function 。
    如果是 tool-use ,则需要更加复杂的场景。
    Scarb
        18
    Scarb  
       52 天前   ❤️ 1
    我感觉你这个用不着这么复杂的流程。
    直接把所有产品名作为上下文给大模型,然后问他:用户问的是产品库里的哪个产品
    dongcxcx
        19
    dongcxcx  
    OP
       52 天前
    @iyaozhen askUser 工具 “调用后必须结束本轮回复” ,之所以加上这条奇怪的规则,是因为在测试中发现,大模型经常会脑补,比如,我故意写一个不支持的产品类型,按理说,askUser 此时应该调用,提示用户补充信息。但是此时 function call 并没有结束,仍然在调用后面的 function call, 它脑补了一个类型,然后调用 parseSku.
    dongcxcx
        20
    dongcxcx  
    OP
       52 天前
    @raydied 我还没接触过微调。我是不是可以理解为,尽可能多的提供 example ,告诉大模型,在不同的情况下,调用不同的 function call, 这样会带来大模型 function call 准确率的提升?
    raydied
        21
    raydied  
       51 天前 via Android
    @dongcxcx 1 、这个做法只能提高 function call 的识别率,感觉并不是此场景的瓶颈。
    2 、还需要重点微调其他方面,预设一些用户问题和期望得到的 json ( slot )。你的场景不复杂,即使穷举,gpt4o 的微调也很便宜。
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   927 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 21:58 · PVG 05:58 · LAX 14:58 · JFK 17:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.