如何减少LangChain+OpenAI查询SQL Server的重复模板Token消耗?
问题描述
我正在用LangChain和OpenAI的gpt-3.5-turbo-16k-0613模型查询SQL Server数据库。LangChain每次查询都会向模型发送固定模板提示(如下),但在包含大量表和列的真实数据库中会触发Token限制——推测是模板里的{table_info}变量占用了大量Token,小型数据库能正常运行,大型数据库就会出问题。我目前在研究Memory、模型微调等方案,想问下有没有办法通过优化单次模板调用减少Token占用,适配真实数据库场景?
LangChain固定提示模板
You are an MS SQL expert. Given an input question, first create a syntactically correct MS SQL query to run, then look at the results of the query and return the answer to the input question. Unless the user specifies in the question a specific number of examples to obtain, query for at most {top_k} results using the TOP clause as per MS SQL. You can order the results to return the most informative data in the database. Never query for all columns from a table. You must query only the columns that are needed to answer the question. Wrap each column name in square brackets ([]) to denote them as delimited identifiers. Pay attention to use only the column names you can see in the tables below. Be careful to not query for columns that do not exist. Also, pay attention to which column is in which table. Use the following format: Question: "Question here" SQLQuery: "SQL Query to run" SQLResult: "Result of the SQLQuery" Answer: "Final answer here" Only use the following tables: {table_info} Question: {input}
我的代码
import openai from langchain import SQLDatabaseChain from langchain.sql_database import SQLDatabase from langchain.llms.openai import OpenAI from sqlalchemy.engine import URL def connect_to_DB(): driver = '{SQL Server}' server = 'MyServer' database = 'NorthWind' # pyodbc connection string connection_string = f'DRIVER={driver};SERVER={server};' connection_string += f'DATABASE={database};' connection_url = URL.create( "mssql+pyodbc", query={"odbc_connect": connection_string}) db = SQLDatabase.from_uri(connection_url, engine_args={"use_setinputsizes":False}) return db if __name__ == '__main__': OPENAI_API_KEY = 'OPENAI_API_KEY' engine = connect_to_DB() llm = OpenAI(temperature=0, verbose=False, openai_api_key=OPENAI_API_KEY, model_name='gpt-3.5-turbo-16k-0613') db_chain = SQLDatabaseChain.from_llm(llm, engine, verbose=True, return_intermediate_steps=True) while True: query = input() print(query) try: result = db_chain(query) result["intermediate_steps"] except openai.error.InvalidRequestError: continue
可行优化方案
只传递关联表结构:不要一次性传入全库表信息,先通过前置LLM调用分析用户问题涉及的表,再仅将这些表的结构传入主模板。LangChain可使用
SQLDatabaseSequentialChain实现分步逻辑:先筛选表,再生成SQL。
示例代码片段:from langchain.chains import SQLDatabaseSequentialChain # 构建分步链,先选表再生成SQL db_chain = SQLDatabaseSequentialChain.from_llm(llm, engine, verbose=True)简化表结构描述:重写表信息提取逻辑,只保留核心内容(表名、列名),去掉冗余的字段类型、注释等。
示例代码片段:def get_simplified_table_info(db, table_names): info = [] for table in table_names: columns = db.get_table_columns(table) col_names = ", ".join([f"[{col.name}]" for col in columns]) info.append(f"表[{table}]包含列:{col_names}") return "\n".join(info)精简提示模板:删除原模板中冗余的规则描述,只保留核心要求,减少模板本身的Token占用。
优化后模板示例:你是MS SQL专家。根据问题生成正确的MS SQL查询,执行后返回答案。 - 未指定数量时最多返回{top_k}条结果,用TOP子句 - 只查询必要列,列名用[]包裹 - 仅使用以下表结构: {table_info} 格式要求: Question: "问题内容" SQLQuery: "SQL语句" SQLResult: "查询结果" Answer: "最终答案" Question: {input}替换默认Chain实现:放弃
SQLDatabaseChain的全量表信息传递逻辑,自定义分步骤Chain,拆分“表筛选→SQL生成→结果解析”流程,降低单次调用的Token负载。
内容的提问来源于stack exchange,提问作者A_Arnold
相关产品推荐
相关产品推荐

