From 6ebbb46c9f3a8acf9edfe82c274fb70503808c28 Mon Sep 17 00:00:00 2001 From: limbo Date: Thu, 18 Dec 2025 21:01:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20AI=20=E8=BE=85=E5=8A=A9=E7=9F=A5?= =?UTF-8?q?=E8=AF=86=E5=BA=93=E6=8F=8F=E8=BF=B0=E7=94=9F=E6=88=90=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/routers/knowledge_router.py | 63 ++++++++++++ web/src/apis/knowledge_api.js | 13 +++ web/src/components/AiTextarea.vue | 120 +++++++++++++++++++++++ web/src/components/DatabaseHeader.vue | 8 +- web/src/components/KnowledgeBaseCard.vue | 8 +- web/src/views/DataBaseView.vue | 6 +- 6 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 web/src/components/AiTextarea.vue diff --git a/server/routers/knowledge_router.py b/server/routers/knowledge_router.py index 97a3369c..79ae3605 100644 --- a/server/routers/knowledge_router.py +++ b/server/routers/knowledge_router.py @@ -1295,3 +1295,66 @@ async def get_all_embedding_models_status(current_user: User = Depends(get_admin except Exception as e: logger.error(f"获取所有embedding模型状态失败: {e}, {traceback.format_exc()}") return {"message": f"获取所有embedding模型状态失败: {e}", "status": {"models": {}, "total": 0, "available": 0}} + + +# ============================================================================= +# === AI 辅助功能分组 === +# ============================================================================= + + +@knowledge.post("/generate-description") +async def generate_description( + name: str = Body(..., description="知识库名称"), + current_description: str = Body("", description="当前描述(可选,用于优化)"), + current_user: User = Depends(get_admin_user), +): + """使用 LLM 生成或优化知识库描述 + + 根据知识库名称和现有描述,使用 LLM 生成适合作为智能体工具描述的内容。 + """ + from src.models import select_model + + logger.debug(f"Generating description for knowledge base: {name}") + + # 构建提示词 + if current_description.strip(): + prompt = textwrap.dedent(f""" + 请帮我优化以下知识库的描述。 + + 知识库名称: {name} + 当前描述: {current_description} + + 要求: + 1. 这个描述将作为智能体工具的描述使用 + 2. 智能体会根据知识库的标题和描述来选择合适的工具 + 3. 所以描述需要清晰、具体,说明该知识库包含什么内容、适合解答什么类型的问题 + 4. 描述应该简洁有力,通常 2-4 句话即可 + 5. 不要使用 Markdown 格式 + + 请直接输出优化后的描述,不要有任何前缀说明。 + """).strip() + else: + prompt = textwrap.dedent(f""" + 请为以下知识库生成一个描述。 + + 知识库名称: {name} + + 要求: + 1. 这个描述将作为智能体工具的描述使用 + 2. 智能体会根据知识库的标题和描述来选择合适的工具 + 3. 所以描述需要清晰、具体,说明该知识库可能包含什么内容、适合解答什么类型的问题 + 4. 描述应该简洁有力,通常 2-4 句话即可 + 5. 不要使用 Markdown 格式 + + 请直接输出描述,不要有任何前缀说明。 + """).strip() + + try: + model = select_model() + response = await asyncio.to_thread(model.call, prompt) + description = response.content.strip() + logger.debug(f"Generated description: {description}") + return {"description": description, "status": "success"} + except Exception as e: + logger.error(f"生成描述失败: {e}, {traceback.format_exc()}") + raise HTTPException(status_code=500, detail=f"生成描述失败: {e}") diff --git a/web/src/apis/knowledge_api.js b/web/src/apis/knowledge_api.js index 63cb7a24..aa3fa638 100644 --- a/web/src/apis/knowledge_api.js +++ b/web/src/apis/knowledge_api.js @@ -53,6 +53,19 @@ export const databaseApi = { */ deleteDatabase: async (dbId) => { return apiAdminDelete(`/api/knowledge/databases/${dbId}`) + }, + + /** + * 使用 AI 生成或优化知识库描述 + * @param {string} name - 知识库名称 + * @param {string} currentDescription - 当前描述(可选) + * @returns {Promise} - 生成结果 + */ + generateDescription: async (name, currentDescription = '') => { + return apiAdminPost('/api/knowledge/generate-description', { + name, + current_description: currentDescription + }) } } diff --git a/web/src/components/AiTextarea.vue b/web/src/components/AiTextarea.vue new file mode 100644 index 00000000..78c9823b --- /dev/null +++ b/web/src/components/AiTextarea.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/web/src/components/DatabaseHeader.vue b/web/src/components/DatabaseHeader.vue index 392e4e6a..2b884876 100644 --- a/web/src/components/DatabaseHeader.vue +++ b/web/src/components/DatabaseHeader.vue @@ -45,7 +45,12 @@ - + @@ -72,6 +77,7 @@ import { } from '@ant-design/icons-vue'; import HeaderComponent from '@/components/HeaderComponent.vue'; import ModelSelectorComponent from '@/components/ModelSelectorComponent.vue'; +import AiTextarea from '@/components/AiTextarea.vue'; import { h } from 'vue'; const router = useRouter(); diff --git a/web/src/components/KnowledgeBaseCard.vue b/web/src/components/KnowledgeBaseCard.vue index 07db1d6f..b2f9b7d6 100644 --- a/web/src/components/KnowledgeBaseCard.vue +++ b/web/src/components/KnowledgeBaseCard.vue @@ -65,7 +65,12 @@ - + @@ -99,6 +104,7 @@ import { CopyOutlined, } from '@ant-design/icons-vue'; import ModelSelectorComponent from '@/components/ModelSelectorComponent.vue'; +import AiTextarea from '@/components/AiTextarea.vue'; const router = useRouter(); const store = useDatabaseStore(); diff --git a/web/src/views/DataBaseView.vue b/web/src/views/DataBaseView.vue index b936c43b..5fa860c9 100644 --- a/web/src/views/DataBaseView.vue +++ b/web/src/views/DataBaseView.vue @@ -81,8 +81,9 @@

知识库描述

在智能体流程中,这里的描述会作为工具的描述。智能体会根据知识库的标题和描述来选择合适的工具。所以这里描述的越详细,智能体越容易选择到合适的工具。

- @@ -244,6 +245,7 @@ import HeaderComponent from '@/components/HeaderComponent.vue'; import ModelSelectorComponent from '@/components/ModelSelectorComponent.vue'; import EmbeddingModelSelector from '@/components/EmbeddingModelSelector.vue'; import dayjs, { parseToShanghai } from '@/utils/time'; +import AiTextarea from '@/components/AiTextarea.vue'; const route = useRoute() const router = useRouter()