You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调优LangChain SQL Agent执行器,使其优先返回姓名而非ID字段

调优LangChain SQL Agent执行器,使其优先返回姓名而非ID字段

我明白你遇到的问题了——SQL Agent有时候会在回答“谁卖得最多?”这类问题时返回用户ID而非姓名,确实挺影响体验的。结合LangChain的配置方式,这里有几个可行的调优方案,你可以试试:

方案一:自定义Prompt模板,给Agent明确指令

SQL Agent的行为很大程度上由Prompt控制,我们可以在系统提示里加入清晰的规则,直接告诉它遇到这类人员相关的问题时要返回姓名而非ID。

from langchain_openai import ChatOpenAI
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.agents import create_sql_agent
from langchain.sql_database import SQLDatabase
from langchain.prompts import PromptTemplate

# 初始化数据库和LLM
db = SQLDatabase.from_uri("你的数据库URI")
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
toolkit = SQLDatabaseToolkit(db=db, llm=llm)

# 自定义Prompt,加入明确的返回规则
custom_prompt = PromptTemplate.from_template("""
你是一个专业的SQL查询助手,负责回答关于数据库的问题。请严格遵循以下规则:
1. 当被问到类似“谁卖得最多?”“哪个用户完成了XX操作?”这类涉及具体人员的问题时,**必须返回该人员的全名(first_name + last_name),绝对不要返回用户ID或其他内部标识字段**。
2. 如果需要关联其他表获取姓名,请自动完成表关联操作,不需要询问用户。
3. 回答要简洁直接,优先给出姓名结果,无需额外解释SQL查询过程,除非用户明确要求。

{input}
{agent_scratchpad}
""")

# 创建Agent并应用自定义Prompt
agent = create_sql_agent(
    llm=llm,
    toolkit=toolkit,
    prompt=custom_prompt,
    verbose=True
)

# 测试示例查询
response = agent.invoke({"input": "哪个用户卖得最多?"})
print(response["output"])

这个方法最直接有效,相当于给Agent立下了明确的“规矩”,LLM会严格遵循Prompt里的指令生成回答。

方案二:增强数据库表结构的语义描述

有时候Agent混淆ID和姓名,是因为它对表字段的用途理解不够清晰。我们可以在初始化数据库时,给表和字段添加更具语义的描述,帮助LLM区分哪些字段是内部标识、哪些是用户需要的展示信息。

# 初始化数据库时,为表和字段添加详细描述
db = SQLDatabase.from_uri(
    "你的数据库URI",
    include_tables=["users", "sales"],  # 指定业务相关的表
    sample_rows_in_table_info=3,  # 提供样本数据,帮助LLM理解数据格式
    table_info="""
    users表存储用户核心信息:
    - user_id: 用户唯一内部ID,仅用于表关联,**绝对不要作为回答返回给用户**
    - first_name: 用户的名字,用于展示用户身份
    - last_name: 用户的姓氏,用于展示用户身份
    sales表存储销售交易记录:
    - sale_id: 销售记录唯一ID
    - user_id: 关联users表的用户内部ID,用于关联查询用户姓名
    - amount: 销售金额
    """
)

# 后续创建Toolkit和Agent的步骤不变
toolkit = SQLDatabaseToolkit(db=db, llm=llm)
agent = create_sql_agent(llm=llm, toolkit=toolkit, verbose=True)

通过明确标注user_id是内部关联字段,LLM在生成SQL和回答时会更倾向于选择first_name和last_name这类展示性字段。

方案三:用输出解析器强制格式化输出

如果前面的方法效果不够理想,还可以添加输出解析器,对Agent的输出进行后处理,强制输出符合要求的姓名格式,避免出现ID。

from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field

# 定义输出格式模型,强制返回姓名
class PersonAnswer(BaseModel):
    full_name: str = Field(description="人员的全名,由first_name和last_name拼接而成,例如:John Doe")

parser = PydanticOutputParser(pydantic_object=PersonAnswer)

# 修改Prompt,要求输出符合指定格式
custom_prompt_with_parser = PromptTemplate.from_template("""
你是一个专业的SQL查询助手,负责回答关于数据库的问题。请遵循以下规则:
1. 当被问到人员相关的问题时,必须返回该人员的全名,绝对不要返回用户ID。
2. 请严格按照以下格式输出:
{format_instructions}

{input}
{agent_scratchpad}
""", partial_variables={"format_instructions": parser.get_format_instructions()})

# 创建Agent
agent = create_sql_agent(
    llm=llm,
    toolkit=toolkit,
    prompt=custom_prompt_with_parser,
    verbose=True
)

# 解析输出,确保得到符合要求的姓名
response = agent.invoke({"input": "哪个用户卖得最多?"})
parsed_result = parser.parse(response["output"])
print(parsed_result.full_name)

这个方法相当于给输出加了一层“过滤器”,确保最终返回的内容完全符合你的需求。

你可以根据自己的数据库结构和实际场景,选择单独使用某个方案,或者组合多个方案来达到最佳效果。

备注:内容来源于stack exchange,提问作者user24243499

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 10:48:09