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

在HF Space中使用GradioUI调用smolagents时SQLite内存表无法检测

解决SQLite内存表在GradioUI中无法访问的问题

问题根源

SQLite的:memory:数据库是每个连接独立的。当Gradio启动后,处理请求时会创建新的进程/线程,此时工具函数sql_engine_tool使用的数据库连接会指向一个全新的空内存实例,而非你初始化时创建的包含receipts表的数据库。

解决方案

将内存数据库替换为磁盘文件数据库,所有连接会共享同一个数据库文件,避免独立内存实例的问题。只需修改数据库连接字符串:

原代码:

engine = create_engine("sqlite:///:memory:")

修改为:

engine = create_engine("sqlite:///receipts.db")

同时确保工具函数能正确访问初始化后的engine和元数据对象,通过全局变量规避作用域问题。

修改后的完整代码

from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, Float, insert, text
from smolagents import tool, CodeAgent, HfApiModel, GradioUI
import os

# 全局变量存储引擎和元数据
engine = None
metadata_objects = None

@tool
def sql_engine_tool(query: str) -> str:
    """
    Allows you to perform SQL queries on the table. Returns a string representation of the result.
    The table is named 'receipts'. Its description is as follows:
        Columns:
        - receipt_id: INTEGER
        - customer_name: VARCHAR(16)
        - price: FLOAT
        - tip: FLOAT

    Args:
        query: The query to perform. This should be correct SQL.

    """
    global engine, metadata_objects
    output = ""
    print("debug sql_engine_tool")
    print(engine)
    with engine.connect() as con:
        print(con.connection)
        print(metadata_objects.tables.keys())
        result = con.execute(
            text(
                "SELECT name FROM sqlite_master WHERE type='table' AND name='receipts'"
            )
        )
        print("tables available:", result.fetchone())

        rows = con.execute(text(query))
        for row in rows:
            output += "\n" + str(row)
    return output


def init_db():
    global engine, metadata_objects
    engine = create_engine("sqlite:///receipts.db")
    metadata_obj = MetaData()

    def insert_rows_into_table(rows, table):
        for row in rows:
            stmt = insert(table).values(**row)
            with engine.begin() as connection:
                connection.execute(stmt)

    table_name = "receipts"
    receipts = Table(
        table_name,
        metadata_obj,
        Column("receipt_id", Integer, primary_key=True),
        Column("customer_name", String(16), primary_key=True),
        Column("price", Float),
        Column("tip", Float),
    )
    metadata_obj.create_all(engine)

    rows = [
        {"receipt_id": 1, "customer_name": "Alan Payne", "price": 12.06, "tip": 1.20},
        {"receipt_id": 2, "customer_name": "Alex Mason", "price": 23.86, "tip": 0.24},
        {
            "receipt_id": 3,
            "customer_name": "Woodrow Wilson",
            "price": 53.43,
            "tip": 5.43,
        },
        {
            "receipt_id": 4,
            "customer_name": "Margaret James",
            "price": 21.11,
            "tip": 1.00,
        },
    ]
    insert_rows_into_table(rows, receipts)
    with engine.begin() as conn:
        print("SELECT test", conn.execute(text("SELECT * FROM receipts")).fetchall())
    print("init_db debug")
    print(engine)
    print()
    metadata_objects = metadata_obj


if __name__ == "__main__":
    init_db()
    model = HfApiModel(
        model_id="meta-llama/Meta-Llama-3.1-8B-Instruct",
        token=os.getenv("my_first_agents_hf_tokens"),
    )

    agent = CodeAgent(
        tools=[sql_engine_tool],
        model=model,
        max_steps=1,
        verbosity_level=1,
    )
    GradioUI(agent).launch()

额外说明

  • 使用磁盘文件数据库后,每次启动应用会检查文件是否存在:存在则直接使用,不存在则重新建表插数据。若需每次启动重置数据,可在init_db开头添加删除receipts.db的逻辑。
  • 全局变量确保sql_engine_tool能获取到正确初始化的数据库实例,避免作用域导致的变量未定义问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 14:52:32