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

解决LangChain+OpenAI操作PostgreSQL大数据库的上下文长度超限错误

解决LangChain SQLDatabaseChain处理大PostgreSQL数据库时的Token超限问题

问题描述

使用LangChain结合OpenAI与PostgreSQL数据库交互,小型数据库运行正常,但数据库规模超过10000行时,触发以下错误:
This model's maximum context length is 4097 tokens. However, your messages resulted in 5100 tokens. Please reduce the length of the messages

可复现该错误的公开数据库为MindsDB房产数据库,连接字符串:

postgresql+psycopg2://demo_user:demo_password@REDACTED:5432/demo

问题代码如下:

import sys
from langchain import OpenAI
from langchain import SQLDatabase
from langchain.chat_models import ChatOpenAI
from langchain_experimental.sql import SQLDatabaseChain

import environ
env = environ.Env()
environ.Env.read_env()

API_KEY = env('OPENAI_API_KEY')

if API_KEY == "":
    print("Missing OpenAPI key")
    exit()

if len(sys.argv) < 2:
    print("Missing db connection string.  Example 'postgresql+psycopg2://postgres:1234@localhost:6667/mydb'")
    exit()

dbstring = sys.argv[1]

print("Using OpenAPI with key ["+API_KEY+"] and Database ["+dbstring+"]")

# Setup database
db = SQLDatabase.from_uri(
    dbstring,
)

# setup llm
llm = ChatOpenAI(model_name="gpt-3.5-turbo",
    temperature=0,
    max_tokens=1000,
    openai_api_key=API_KEY)

# Create db chain
QUERY = """
Given an input question, first create a syntactically correct postgresql query to run, then look at the results of the query and return the answer.
Use the following format:

Question: Question here
SQLQuery: SQL Query to run
SQLResult: Result of the SQLQuery
Answer: Final answer here

{question}
"""

# Setup the database chain
db_chain = SQLDatabaseChain(llm=llm, database=db, verbose=True)

def get_prompt():
    print("Type 'exit' to quit")

    while True:
        prompt = input("Enter a prompt: ")

        if prompt.lower() == 'exit':
            print('Exiting...')
            break
        else:
            try:
                question = QUERY.format(question=prompt)
                print(db_chain.run(question))
            except Exception as e:
                print(e)

get_prompt()

核心原因

SQLDatabaseChain默认会将全量表结构+完整查询结果集打包传入LLM上下文,当数据库表字段多、行数多,或查询返回大量数据时,总token数会超出gpt-3.5-turbo的4097上限。

解决方案

1. 限制加载的数据库表

初始化SQLDatabase时,仅加载业务相关的表,避免无关表结构占用token:

db = SQLDatabase.from_uri(
    dbstring,
    include_tables=['target_table_name']  # 替换为实际需要的表名
)

2. 限制查询结果行数

通过配置限制单次查询返回的行数,减少结果集的token占用:

db_chain = SQLDatabaseChain.from_llm(
    llm=llm,
    database=db,
    verbose=True,
    sql_database_kwargs={"max_rows": 50}  # 单次查询最多返回50行,可按需调整
)

3. 切换大上下文模型

改用支持更大token容量的模型,直接提升上下文处理能力:

llm = ChatOpenAI(model_name="gpt-3.5-turbo-16k",  # 支持16384 token
    temperature=0,
    max_tokens=1000,
    openai_api_key=API_KEY)

4. 精简Prompt模板

删除冗余描述,减少固定模板的token开销:

QUERY = """
根据问题生成合法PostgreSQL查询,执行后返回答案:
问题:{question}
SQL查询:
执行结果:
答案:
"""

5. 使用多步链式查询

用SQLDatabaseSequentialChain将复杂任务拆分为多步执行,每步仅传递必要上下文:

from langchain.chains import SQLDatabaseSequentialChain

db_chain = SQLDatabaseSequentialChain.from_llm(
    llm=llm,
    database=db,
    verbose=True,
    top_k=50  # 限制每步查询结果行数
)

内容的提问来源于stack exchange,提问作者steve landiss

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 09:51:13