From 0f537a9cad280f0432ee777af642cf1056239bbf Mon Sep 17 00:00:00 2001 From: ThearchyHelios Date: Sun, 4 Oct 2026 01:31:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AA=E6=8E=A2=E6=9F=A5=E4=BA=86=E9=83=A8?= =?UTF-8?q?=E5=88=86=E8=A1=A8=E6=97=B6=EF=BC=8C=E6=9F=A5=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E4=B8=8D=E5=86=8D=E5=AF=B9=E6=B2=A1=E6=8E=A2?= =?UTF-8?q?=E6=9F=A5=E5=88=B0=E7=9A=84=E8=A1=A8=E8=AF=B4=E3=80=8C=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E3=80=8D=EF=BC=9A=E8=AF=B4=E6=98=8E=E4=B8=8D=E5=9C=A8?= =?UTF-8?q?=E5=B7=B2=E6=8E=A2=E6=9F=A5=E8=8C=83=E5=9B=B4=E3=80=81=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E5=88=A4=E6=96=AD=EF=BC=8C=E5=B9=B6=E7=BB=99=E5=87=BA?= =?UTF-8?q?=E6=9F=A5=E6=95=B0=E6=8D=AE=E5=AD=97=E5=85=B8=E7=9A=84=E5=8A=9E?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/data/introspect.py | 9 +++++++++ backend/tests/test_catalog_schema_truncated.py | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/backend/app/data/introspect.py b/backend/app/data/introspect.py index 27ab77e1..ea8875be 100644 --- a/backend/app/data/introspect.py +++ b/backend/app/data/introspect.py @@ -447,6 +447,15 @@ def describe_table(source: Any, table: str, *, catalog: Mapping[str, Mapping[str available = "、".join( m.get("qualified", n) for n, m in list(tables.items())[:30] ) + if cache.get("truncated"): + # 只探查了一部分表:没探查到不等于没有。以前照样回「中没有 X」,模型据此换了别的表或者编答案 + total = cache.get("total") + of = f"共 {total} 个对象," if isinstance(total, int) else "" + return ( + f"数据源「{source.name}」{of}只探查了其中 {len(tables)} 个,{table} 不在已探查的范围内," + "无法判断是否存在。请直接查询数据字典(information_schema.tables / columns,SQLite 用 " + f"sqlite_master)确认它的结构。已探查的对象包括:{available}" + ) return f"数据源「{source.name}」中没有 {table}。现有的对象:{available}" head = f"{'视图' if meta.get('is_view') else '表'} {meta.get('qualified', table)}" diff --git a/backend/tests/test_catalog_schema_truncated.py b/backend/tests/test_catalog_schema_truncated.py index b16489d2..4477b7f8 100644 --- a/backend/tests/test_catalog_schema_truncated.py +++ b/backend/tests/test_catalog_schema_truncated.py @@ -114,3 +114,20 @@ async def test_assistant_context_of_a_complete_schema_says_nothing_extra(narrow) (row,) = ctx.op()["sources"] assert row["total"] == 3 and "explored" not in row assert "没有探查到" not in ctx.section() + + +async def test_schema_tool_does_not_deny_a_table_that_was_not_introspected(wide, narrow): + """只探查了一部分表时,查一张没探查到的表不能说「没有」:它可能就在没探查到的那部分里。 + 以前回「数据源中没有 X」,模型据此改用别的表,或者编一个答案。""" + from app.data.introspect import describe_table + + row = await _row(wide[0]) + explored = set((row.schema_cache or {}).get("tables") or {}) + missing = next(f"t{i:03d}" for i in range(WIDE) if f"t{i:03d}" not in explored) + text = describe_table(row, missing) + assert "中没有" not in text + assert "只探查了" in text and "information_schema" in text + + # 探查完整的库:查不存在的表照旧说没有 + small = await _row(narrow[0]) + assert "中没有 nope" in describe_table(small, "nope")