feat: 增加工具配置说明展示

This commit is contained in:
Wenjie Zhang 2026-03-30 16:39:27 +08:00
parent fa5a2fa1ae
commit d282cab00c
8 changed files with 115 additions and 2 deletions

View File

@ -20,6 +20,15 @@ from yuxi.utils.question_utils import normalize_questions
# Lazy initialization for TavilySearch (only when API key is available)
_tavily_search_instance = None
QWEN_IMAGE_CONFIG_GUIDE = """
使用前需要先配置硅基流动的图片生成访问凭证
请在后端运行环境中配置环境变量
- `SILICONFLOW_API_KEY`用于调用 SiliconFlow 的图片生成接口
配置完成后即可使用该工具生成图片
""".strip()
def _create_tavily_search():
"""Create and register TavilySearch tool with metadata."""
@ -280,7 +289,12 @@ def query_knowledge_graph(query: Annotated[str, "The keyword to query knowledge
return f"知识图谱查询失败: {str(e)}"
@tool(category="buildin", tags=["图片", "生成"], display_name="Qwen-Image")
@tool(
category="buildin",
tags=["图片", "生成"],
display_name="Qwen-Image",
config_guide=QWEN_IMAGE_CONFIG_GUIDE,
)
async def text_to_img_qwen_image(
prompt: Annotated[str, "用于生成图片的文本描述"],
negative_prompt: Annotated[str, "负面提示词,用于指定不想出现在图片中的元素"] = "",

View File

@ -17,6 +17,22 @@ from .security import MySQLSecurityChecker
# 全局连接管理器实例
_connection_manager: MySQLConnectionManager | None = None
MYSQL_CONFIG_GUIDE = """
使用前需要先配置 MySQL 连接相关环境变量
必填环境变量
- `MYSQL_HOST`
- `MYSQL_PORT`
- `MYSQL_USER`
- `MYSQL_PASSWORD`
- `MYSQL_DATABASE`
可选环境变量
- `MYSQL_DATABASE_DESCRIPTION`数据库说明会追加到工具描述中帮助模型理解库表语义
请在后端运行环境中完成以上配置后再使用这些 MySQL 工具
""".strip()
def get_connection_manager() -> MySQLConnectionManager:
"""获取全局连接管理器"""
@ -50,6 +66,7 @@ def get_connection_manager() -> MySQLConnectionManager:
category="mysql",
tags=["数据库", "查询"],
display_name="列出MySQL表",
config_guide=MYSQL_CONFIG_GUIDE,
name_or_callable="mysql_list_tables",
)
def mysql_list_tables() -> str:
@ -110,6 +127,7 @@ class TableDescribeModel(BaseModel):
category="mysql",
tags=["数据库", "结构"],
display_name="描述MySQL表结构",
config_guide=MYSQL_CONFIG_GUIDE,
name_or_callable="mysql_describe_table",
args_schema=TableDescribeModel,
)
@ -212,6 +230,7 @@ class QueryModel(BaseModel):
category="mysql",
tags=["数据库", "SQL"],
display_name="执行MySQL查询",
config_guide=MYSQL_CONFIG_GUIDE,
name_or_callable="mysql_query",
args_schema=QueryModel,
)

View File

@ -10,6 +10,7 @@ class ToolExtraMetadata:
tags: list[str] = field(default_factory=list)
display_name: str = "" # 显示名称(给人看的名字)
icon: str = ""
config_guide: str = "" # 配置说明(给人看的使用前配置提示)
# 全局注册表: tool_name -> ToolExtraMetadata
@ -40,6 +41,7 @@ def tool(
tags: list[str] = None,
display_name: str = "",
icon: str = "",
config_guide: str = "",
name_or_callable: str | Callable | None = None,
description: str | None = None,
args_schema: type | None = None,
@ -83,6 +85,7 @@ def tool(
tags=tags or [],
display_name=display_name,
icon=icon,
config_guide=config_guide,
)
# 自动收集工具实例

View File

@ -55,6 +55,7 @@ def _ensure_metadata_loaded():
extra = extra_meta[tool_name]
runtime_info["category"] = extra.category
runtime_info["tags"] = extra.tags
runtime_info["config_guide"] = extra.config_guide
# display_name 优先级高于 tool.name
if extra.display_name:
runtime_info["name"] = extra.display_name
@ -62,6 +63,7 @@ def _ensure_metadata_loaded():
# 未注册,设为默认分类
runtime_info["category"] = "buildin"
runtime_info["tags"] = []
runtime_info["config_guide"] = ""
_metadata_cache.append(runtime_info)

View File

@ -38,3 +38,14 @@ async def test_admin_can_fetch_config_and_reload_info(test_client, admin_headers
reload_payload = reload_response.json()
assert reload_payload["success"] is True
assert "data" in reload_payload
async def test_admin_can_fetch_tools_with_config_guide_field(test_client, admin_headers):
response = await test_client.get("/api/system/tools", headers=admin_headers)
assert response.status_code == 200, response.text
payload = response.json()
assert payload["success"] is True
assert isinstance(payload["data"], list)
assert payload["data"]
assert "config_guide" in payload["data"][0]

View File

@ -0,0 +1,48 @@
from __future__ import annotations
from types import SimpleNamespace
from yuxi.services import tool_service
def test_get_tool_metadata_includes_config_guide(monkeypatch):
tool_service._metadata_cache.clear()
fake_tool = SimpleNamespace(
name="demo_tool",
description="demo description",
metadata={},
args_schema=None,
)
fake_extra = SimpleNamespace(
category="buildin",
tags=["demo"],
display_name="演示工具",
config_guide="请先配置 DEMO_API_KEY",
)
monkeypatch.setattr(
"yuxi.agents.toolkits.registry.get_all_tool_instances",
lambda: [fake_tool],
)
monkeypatch.setattr(
"yuxi.agents.toolkits.registry.get_all_extra_metadata",
lambda: {"demo_tool": fake_extra},
)
result = tool_service.get_tool_metadata()
assert result == [
{
"id": "demo_tool",
"name": "演示工具",
"description": "demo description",
"metadata": {},
"args": [],
"category": "buildin",
"tags": ["demo"],
"config_guide": "请先配置 DEMO_API_KEY",
}
]
tool_service._metadata_cache.clear()

View File

@ -48,6 +48,7 @@
- 重构内置 Skills/MCP/Subagents 安装/添加/移除机制:内置 skill 支持按需安装、基于 `version + content_hash` 的更新提示与覆盖确认,不再使用服务器级开关切换
- 新增知识库 PDF、图片的预览功能
- 重构后端测试目录结构:按 `unit / integration / e2e` 分层迁移现有测试,拆分全局 `conftest.py`,统一测试入口为 `uv run --group test pytest`,并新增独立测试规范文档 `docs/vibe/testing-guidelines.md`
- 新增工具元数据 `config_guide` 字段:后端工具列表接口现在可返回“给人看的配置说明”,前端工具详情页会展示该说明,用于提示工具使用前需要配置的环境变量或入口;首批为 MySQL 工具和 `Qwen-Image` 补充了配置指引
<!-- 添加到这里 -->

View File

@ -101,6 +101,16 @@
</div>
</div>
<div class="detail-section" v-if="currentTool.config_guide">
<div class="section-header">
<FileText :size="14" />
<span>配置说明</span>
</div>
<div class="section-content description config-guide">
{{ currentTool.config_guide }}
</div>
</div>
<div class="detail-section">
<div class="section-header">
<Tag :size="14" />
@ -190,7 +200,8 @@ const filteredTools = computed(() => {
(t) =>
t.name.toLowerCase().includes(q) ||
t.id.toLowerCase().includes(q) ||
t.description?.toLowerCase().includes(q)
t.description?.toLowerCase().includes(q) ||
t.config_guide?.toLowerCase().includes(q)
)
}
return result
@ -261,4 +272,8 @@ defineExpose({
font-size: 12px;
}
}
.config-guide {
white-space: pre-line;
}
</style>