diff --git a/docs/docs/agents/introduction/tools_use.md b/docs/docs/agents/introduction/tools_use.md new file mode 100644 index 000000000..ce5591e6c --- /dev/null +++ b/docs/docs/agents/introduction/tools_use.md @@ -0,0 +1,182 @@ +# Tool Use + +While LLMs can complete a wide range of tasks, they may not work well for the domains +which need comprehensive expert knowledge. In addition, LLMs may also encounter +hallucination problems, which are hard to be resolved by themselves. + +So, we need to use some tools to help LLMs to complete the tasks. + +:::note +In DB-GPT agents, most LLMs support tool calls as long as their own capabilities are not too weak. +(Such as `glm-4-9b-chat`, `Yi-1.5-34B-Chat`, `Qwen2-72B-Instruct`, etc.) +::: + +## Writing Tools + +Sometimes, LLMs may not be able to complete the calculation tasks directly, so we can +write a simple calculator tool to help them. +```python +from dbgpt.agent.resource import tool + +@tool +def simple_calculator(first_number: int, second_number: int, operator: str) -> float: + """Simple calculator tool. Just support +, -, *, /.""" + if isinstance(first_number, str): + first_number = int(first_number) + if isinstance(second_number, str): + second_number = int(second_number) + if operator == "+": + return first_number + second_number + elif operator == "-": + return first_number - second_number + elif operator == "*": + return first_number * second_number + elif operator == "/": + return first_number / second_number + else: + raise ValueError(f"Invalid operator: {operator}") +``` + +To test multiple tools, let's write another tool to help LLMs to count the number of files in a directory. + +```python +import os +from typing_extensions import Annotated, Doc + +@tool +def count_directory_files(path: Annotated[str, Doc("The directory path")]) -> int: + """Count the number of files in a directory.""" + if not os.path.isdir(path): + raise ValueError(f"Invalid directory path: {path}") + return len(os.listdir(path)) +``` +## Wrap Your Tools To `ToolPack` + +Most of the time, you may have multiple tools, so you can wrap them to a `ToolPack`. +`ToolPack` is a collection of tools, you can use it to manage your tools, and the agent +can select the appropriate tool from the `ToolPack` according to the task requirements. + +```python +from dbgpt.agent.resource import ToolPack + +tools = ToolPack([simple_calculator, count_directory_files]) +``` + +## Use Tools In Your Agent + +```python +import asyncio +import os +from dbgpt.agent import AgentContext, AgentMemory, LLMConfig, UserProxyAgent +from dbgpt.agent.expand.tool_assistant_agent import ToolAssistantAgent +from dbgpt.model.proxy import OpenAILLMClient + +async def main(): + + llm_client = OpenAILLMClient( + model_alias="gpt-3.5-turbo", # or other models, eg. "gpt-4o" + api_base=os.getenv("OPENAI_API_BASE"), + api_key=os.getenv("OPENAI_API_KEY"), + ) + context: AgentContext = AgentContext( + conv_id="test123", language="en", temperature=0.5, max_new_tokens=2048 + ) + agent_memory = AgentMemory() + agent_memory.gpts_memory.init(conv_id="test123") + + user_proxy = await UserProxyAgent().bind(agent_memory).bind(context).build() + + tool_man = ( + await ToolAssistantAgent() + .bind(context) + .bind(LLMConfig(llm_client=llm_client)) + .bind(agent_memory) + .bind(tools) + .build() + ) + + await user_proxy.initiate_chat( + recipient=tool_man, + reviewer=user_proxy, + message="Calculate the product of 10 and 99", + ) + + await user_proxy.initiate_chat( + recipient=tool_man, + reviewer=user_proxy, + message="Count the number of files in /tmp", + ) + + # dbgpt-vis message infos + print(await agent_memory.gpts_memory.app_link_chat_message("test123")) + +if __name__ == "__main__": + asyncio.run(main()) + +``` +The output will be like this: +``````bash +-------------------------------------------------------------------------------- +User (to LuBan)-[]: + +"Calculate the product of 10 and 99" + +-------------------------------------------------------------------------------- +un_stream ai response: { + "thought": "To calculate the product of 10 and 99, we need to use a tool that can perform multiplication operation.", + "tool_name": "simple_calculator", + "args": { + "first_number": 10, + "second_number": 99, + "operator": "*" + } +} + +-------------------------------------------------------------------------------- +LuBan (to User)-[gpt-3.5-turbo]: + +"{\n \"thought\": \"To calculate the product of 10 and 99, we need to use a tool that can perform multiplication operation.\",\n \"tool_name\": \"simple_calculator\",\n \"args\": {\n \"first_number\": 10,\n \"second_number\": 99,\n \"operator\": \"*\"\n }\n}" +>>>>>>>>LuBan Review info: +Pass(None) +>>>>>>>>LuBan Action report: +execution succeeded, +990 + +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +User (to LuBan)-[]: + +"Count the number of files in /tmp" + +-------------------------------------------------------------------------------- +un_stream ai response: { + "thought": "To count the number of files in /tmp directory, we should use a tool that can perform this operation.", + "tool_name": "count_directory_files", + "args": { + "path": "/tmp" + } +} + +-------------------------------------------------------------------------------- +LuBan (to User)-[gpt-3.5-turbo]: + +"{\n \"thought\": \"To count the number of files in /tmp directory, we should use a tool that can perform this operation.\",\n \"tool_name\": \"count_directory_files\",\n \"args\": {\n \"path\": \"/tmp\"\n }\n}" +>>>>>>>>LuBan Review info: +Pass(None) +>>>>>>>>LuBan Action report: +execution succeeded, +19 + +-------------------------------------------------------------------------------- +`````` + + +In the above code, we use the `ToolAssistantAgent` to select and call the appropriate tool. + +## More Details? + +In the above code, we use the `tool` decorator to define the tool function. It will wrap the function to a +`FunctionTool` object. And `FunctionTool` is a subclass of `BaseTool`, which is a base class of all tools. + +Actually, **tool** is a special **resource** in the `DB-GPT` agent. You will see more details in the [Resource](../modules/resource/resource.md) section. \ No newline at end of file diff --git a/docs/docs/application/awel.md b/docs/docs/application/awel.md index 84efc4669..15c50acfc 100644 --- a/docs/docs/application/awel.md +++ b/docs/docs/application/awel.md @@ -108,3 +108,7 @@ After that, you can use it to build your APP according to [App Manage](./apps/ap - [AWEL](../awel/awel.md) - [AWEL CookBook](../awel/cookbook/) - [AWEL Tutorial](../awel/tutorial/) + +--- + +📖 Want to learn more about AWEL? Check out the [AWEL Tutorial](../awel/tutorial/) for step-by-step guides from basics to advanced patterns. diff --git a/docs/i18n/zh-CN/docusaurus-plugin-content-docs/current.json b/docs/i18n/zh-CN/docusaurus-plugin-content-docs/current.json index 81f816d85..a00b71be9 100644 --- a/docs/i18n/zh-CN/docusaurus-plugin-content-docs/current.json +++ b/docs/i18n/zh-CN/docusaurus-plugin-content-docs/current.json @@ -55,6 +55,10 @@ "message": "数据源", "description": "The label for category Datasources in sidebar docsSidebar" }, + "sidebar.docsSidebar.category.Application": { + "message": "应用管理", + "description": "The label for category Application in sidebar docsSidebar" + }, "sidebar.docsSidebar.category.App Guides": { "message": "应用指南", "description": "The label for category App Guides in sidebar docsSidebar" @@ -307,8 +311,12 @@ "message": "GraphRAG", "description": "The label for the doc item GraphRAG in sidebar docsSidebar, linking to the doc application/graph_rag" }, + "sidebar.docsSidebar.doc.App Manage": { + "message": "应用管理", + "description": "The label for the doc item App Manage in sidebar docsSidebar, linking to the doc application/apps/app_manage" + }, "sidebar.docsSidebar.doc.Chat Knowledge Base": { - "message": "Chat Knowledge Base", + "message": "知识库对话", "description": "The label for the doc item Chat Knowledge Base in sidebar docsSidebar, linking to the doc application/apps/chat_knowledge" }, "sidebar.docsSidebar.doc.Advanced RAG": { @@ -370,5 +378,53 @@ "sidebar.docsSidebar.doc.Use Cases": { "message": "使用案例", "description": "The label for the doc item Use Cases in sidebar docsSidebar, linking to the doc use_cases" + }, + "sidebar.sidebarApplication.category.App Guides": { + "message": "应用指南", + "description": "The label for category App Guides in sidebar sidebarApplication" + }, + "sidebar.sidebarApplication.category.Functional Components": { + "message": "功能组件", + "description": "The label for category Functional Components in sidebar sidebarApplication" + }, + "sidebar.sidebarApplication.doc.App Manage": { + "message": "应用管理", + "description": "The label for the doc item App Manage in sidebar sidebarApplication, linking to the doc application/apps/app_manage" + }, + "sidebar.sidebarApplication.doc.Chat Knowledge Base": { + "message": "知识库对话", + "description": "The label for the doc item Chat Knowledge Base in sidebar sidebarApplication, linking to the doc application/apps/chat_knowledge" + }, + "sidebar.sidebarApplication.doc.Chat Data": { + "message": "Chat Data", + "description": "The label for the doc item Chat Data in sidebar sidebarApplication, linking to the doc application/apps/chat_data" + }, + "sidebar.sidebarApplication.doc.Chat DB": { + "message": "Chat DB", + "description": "The label for the doc item Chat DB in sidebar sidebarApplication, linking to the doc application/apps/chat_db" + }, + "sidebar.sidebarApplication.doc.Chat Excel": { + "message": "Chat Excel", + "description": "The label for the doc item Chat Excel in sidebar sidebarApplication, linking to the doc application/apps/chat_excel" + }, + "sidebar.sidebarApplication.doc.Chat Dashboard": { + "message": "Chat Dashboard", + "description": "The label for the doc item Chat Dashboard in sidebar sidebarApplication, linking to the doc application/apps/chat_dashboard" + }, + "sidebar.sidebarApplication.doc.Prompts": { + "message": "提示词", + "description": "The label for the doc item Prompts in sidebar sidebarApplication, linking to the doc application/prompts" + }, + "sidebar.sidebarApplication.doc.LLMs": { + "message": "模型管理", + "description": "The label for the doc item LLMs in sidebar sidebarApplication, linking to the doc application/llms" + }, + "sidebar.sidebarApplication.doc.Use Data App With AWEL": { + "message": "使用 AWEL 构建数据应用", + "description": "The label for the doc item Use Data App With AWEL in sidebar sidebarApplication, linking to the doc application/awel" + }, + "sidebar.sidebarApplication.doc.Benchmark": { + "message": "基准测试", + "description": "The label for the doc item Benchmark in sidebar sidebarApplication, linking to the doc modules/benchmark" } } diff --git a/docs/i18n/zh-CN/docusaurus-plugin-content-docs/current/agents/introduction/tools_use.md b/docs/i18n/zh-CN/docusaurus-plugin-content-docs/current/agents/introduction/tools_use.md new file mode 100644 index 000000000..0135ed0b1 --- /dev/null +++ b/docs/i18n/zh-CN/docusaurus-plugin-content-docs/current/agents/introduction/tools_use.md @@ -0,0 +1,178 @@ +# 工具使用 + +虽然大语言模型(LLM)可以完成各种各样的任务,但在需要全面专业知识的领域中,它们可能表现不佳。此外,LLM 还可能遇到幻觉问题,而这些问题很难靠自身解决。 + +因此,我们需要使用一些工具来帮助 LLM 完成任务。 + +:::note +在 DB-GPT 智能体中,大多数 LLM 都支持工具调用,只要其自身能力不是太弱即可。 +(例如 `glm-4-9b-chat`、`Yi-1.5-34B-Chat`、`Qwen2-72B-Instruct` 等) +::: + +## 编写工具 + +有时候,LLM 可能无法直接完成计算任务,因此我们可以编写一个简单的计算器工具来帮助它们。 +```python +from dbgpt.agent.resource import tool + +@tool +def simple_calculator(first_number: int, second_number: int, operator: str) -> float: + """Simple calculator tool. Just support +, -, *, /.""" + if isinstance(first_number, str): + first_number = int(first_number) + if isinstance(second_number, str): + second_number = int(second_number) + if operator == "+": + return first_number + second_number + elif operator == "-": + return first_number - second_number + elif operator == "*": + return first_number * second_number + elif operator == "/": + return first_number / second_number + else: + raise ValueError(f"Invalid operator: {operator}") +``` + +为了测试多个工具,我们再编写一个工具来帮助 LLM 统计目录中的文件数量。 + +```python +import os +from typing_extensions import Annotated, Doc + +@tool +def count_directory_files(path: Annotated[str, Doc("The directory path")]) -> int: + """Count the number of files in a directory.""" + if not os.path.isdir(path): + raise ValueError(f"Invalid directory path: {path}") + return len(os.listdir(path)) +``` + +## 将工具封装为 `ToolPack` + +大多数情况下,你可能有多个工具,因此可以将它们封装为一个 `ToolPack`。 +`ToolPack` 是工具的集合,你可以用它来管理你的工具,智能体可以根据任务需求从 `ToolPack` 中选择合适的工具。 + +```python +from dbgpt.agent.resource import ToolPack + +tools = ToolPack([simple_calculator, count_directory_files]) +``` + +## 在智能体中使用工具 + +```python +import asyncio +import os +from dbgpt.agent import AgentContext, AgentMemory, LLMConfig, UserProxyAgent +from dbgpt.agent.expand.tool_assistant_agent import ToolAssistantAgent +from dbgpt.model.proxy import OpenAILLMClient + +async def main(): + + llm_client = OpenAILLMClient( + model_alias="gpt-3.5-turbo", # 或其他模型,例如 "gpt-4o" + api_base=os.getenv("OPENAI_API_BASE"), + api_key=os.getenv("OPENAI_API_KEY"), + ) + context: AgentContext = AgentContext( + conv_id="test123", language="en", temperature=0.5, max_new_tokens=2048 + ) + agent_memory = AgentMemory() + agent_memory.gpts_memory.init(conv_id="test123") + + user_proxy = await UserProxyAgent().bind(agent_memory).bind(context).build() + + tool_man = ( + await ToolAssistantAgent() + .bind(context) + .bind(LLMConfig(llm_client=llm_client)) + .bind(agent_memory) + .bind(tools) + .build() + ) + + await user_proxy.initiate_chat( + recipient=tool_man, + reviewer=user_proxy, + message="Calculate the product of 10 and 99", + ) + + await user_proxy.initiate_chat( + recipient=tool_man, + reviewer=user_proxy, + message="Count the number of files in /tmp", + ) + + # dbgpt-vis 消息信息 + print(await agent_memory.gpts_memory.app_link_chat_message("test123")) + +if __name__ == "__main__": + asyncio.run(main()) + +``` + +输出结果如下: +```bash +-------------------------------------------------------------------------------- +User (to LuBan)-[]: + +"Calculate the product of 10 and 99" + +-------------------------------------------------------------------------------- +un_stream ai response: { + "thought": "To calculate the product of 10 and 99, we need to use a tool that can perform multiplication operation.", + "tool_name": "simple_calculator", + "args": { + "first_number": 10, + "second_number": 99, + "operator": "*" + } +} + +-------------------------------------------------------------------------------- +LuBan (to User)-[gpt-3.5-turbo]: + +"{\n \"thought\": \"To calculate the product of 10 and 99, we need to use a tool that can perform multiplication operation.\",\n \"tool_name\": \"simple_calculator\",\n \"args\": {\n \"first_number\": 10,\n \"second_number\": 99,\n \"operator\": \"*\"\n }\n}" +>>>>>>>>LuBan Review info: +Pass(None) +>>>>>>>>LuBan Action report: +execution succeeded, +990 + +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +User (to LuBan)-[]: + +"Count the number of files in /tmp" + +-------------------------------------------------------------------------------- +un_stream ai response: { + "thought": "To count the number of files in /tmp directory, we should use a tool that can perform this operation.", + "tool_name": "count_directory_files", + "args": { + "path": "/tmp" + } +} + +-------------------------------------------------------------------------------- +LuBan (to User)-[gpt-3.5-turbo]: + +"{\n \"thought\": \"To count the number of files in /tmp directory, we should use a tool that can perform this operation.\",\n \"tool_name\": \"count_directory_files\",\n \"args\": {\n \"path\": \"/tmp\"\n }\n}" +>>>>>>>>LuBan Review info: +Pass(None) +>>>>>>>>LuBan Action report: +execution succeeded, +19 + +-------------------------------------------------------------------------------- +``` + +在上面的代码中,我们使用 `ToolAssistantAgent` 来选择并调用合适的工具。 + +## 更多细节? + +在上面的代码中,我们使用 `tool` 装饰器来定义工具函数。它会将函数封装为一个 `FunctionTool` 对象。而 `FunctionTool` 是 `BaseTool` 的子类,`BaseTool` 是所有工具的基类。 + +实际上,**工具**是 `DB-GPT` 智能体中一种特殊的**资源**。你可以在[资源](../modules/resource/resource.md)章节中了解更多细节。 diff --git a/docs/sidebars.js b/docs/sidebars.js index 4a56317b1..5319300ab 100755 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -154,6 +154,8 @@ const sidebars = { { type: "category", label: "Datasource Integrations", + collapsed: true, + collapsible: true, items: [ { type: "doc", id: "installation/integrations/mysql_install" }, { type: "doc", id: "installation/integrations/sqlite_install" }, @@ -406,6 +408,7 @@ const sidebars = { type: "category", label: "Datasource Integrations", collapsed: true, + collapsible: true, items: [ { type: "doc", id: "installation/integrations/clickhouse_install" }, { type: "doc", id: "installation/integrations/postgres_install" }, @@ -556,8 +559,8 @@ const sidebars = { { type: "category", label: "Datasource Integrations", - collapsed: false, - collapsible: false, + collapsed: true, + collapsible: true, items: [ { type: "doc", id: "installation/integrations/mysql_install" }, { type: "doc", id: "installation/integrations/sqlite_install" }, @@ -574,19 +577,36 @@ const sidebars = { { type: "doc", id: "installation/integrations/vertica_install" }, ], }, + ], + + sidebarApplication: [ { type: "category", label: "App Guides", collapsed: false, - collapsible: false, + collapsible: true, items: [ + { type: "doc", id: "application/apps/app_manage", label: "App Manage" }, { type: "doc", id: "application/apps/chat_data", label: "Chat Data" }, { type: "doc", id: "application/apps/chat_db", label: "Chat DB" }, { type: "doc", id: "application/apps/chat_excel", label: "Chat Excel" }, + { type: "doc", id: "application/apps/chat_knowledge", label: "Chat Knowledge Base" }, { type: "doc", id: "application/apps/chat_dashboard", label: "Chat Dashboard" }, { type: "doc", id: "application/apps/chat_financial_report" }, ], }, + { + type: "category", + label: "Functional Components", + collapsed: false, + collapsible: true, + items: [ + { type: "doc", id: "application/prompts", label: "Prompts" }, + { type: "doc", id: "application/llms", label: "LLMs" }, + { type: "doc", id: "application/awel", label: "Use Data App With AWEL" }, + { type: "doc", id: "modules/benchmark", label: "Benchmark" }, + ], + }, ], sidebarSandbox: [{ type: "doc", id: "sandbox/index", label: "Overview" }], @@ -777,6 +797,75 @@ const sidebars = { }, ], + sidebarDevelopmentGuide: [ + { + type: "category", + label: "Agents", + collapsed: true, + items: [ + { type: "doc", id: "agents/introduction/introduction", label: "Data Driven Multi-Agents" }, + { type: "doc", id: "agents/introduction/tools_use", label: "Tool Use" }, + { type: "doc", id: "agents/introduction/planning", label: "Planning" }, + { type: "doc", id: "agents/introduction/conversation", label: "Conversation" }, + { type: "doc", id: "agents/introduction/custom_agents", label: "Custom Agents" }, + { + type: "category", + label: "Agent Modules", + collapsed: true, + items: [ + { + type: "category", + label: "Profile", + collapsed: true, + items: [ + { type: "doc", id: "agents/modules/profile/profile" }, + { type: "doc", id: "agents/modules/profile/profile_creation" }, + { type: "doc", id: "agents/modules/profile/profile_to_prompt" }, + { type: "doc", id: "agents/modules/profile/profile_dynamic" }, + ], + }, + { + type: "category", + label: "Memory", + collapsed: true, + items: [ + { type: "doc", id: "agents/modules/memory/memory" }, + { type: "doc", id: "agents/modules/memory/sensory_memory" }, + { type: "doc", id: "agents/modules/memory/short_term_memory" }, + { type: "doc", id: "agents/modules/memory/long_term_memory" }, + { type: "doc", id: "agents/modules/memory/hybrid_memory" }, + ], + }, + { + type: "category", + label: "Plan", + collapsed: true, + items: [{ type: "doc", id: "agents/modules/plan/plan" }], + }, + { + type: "category", + label: "Action", + collapsed: true, + items: [{ type: "doc", id: "agents/modules/action/action" }], + }, + { + type: "category", + label: "Resource", + collapsed: true, + items: [ + { type: "doc", id: "agents/modules/resource/resource" }, + { type: "doc", id: "agents/modules/resource/tools" }, + { type: "doc", id: "agents/modules/resource/database" }, + { type: "doc", id: "agents/modules/resource/knowledge" }, + { type: "doc", id: "agents/modules/resource/pack" }, + ], + }, + ], + }, + ], + }, + ], + sidebarReference: [ { type: "category", @@ -819,7 +908,6 @@ const sidebars = { }, { type: "doc", id: "modules/visual", label: "Visual" }, { type: "doc", id: "modules/eval", label: "Evaluation" }, - { type: "doc", id: "modules/benchmark", label: "Benchmark" }, ], sidebarHelp: [ @@ -890,6 +978,13 @@ module.exports = { collapsible: true, items: sidebars.sidebarDatasources, }, + { + type: "category", + label: "Application", + collapsed: true, + collapsible: true, + items: sidebars.sidebarApplication, + }, { type: "category", label: "Sandbox", @@ -932,6 +1027,13 @@ module.exports = { collapsible: true, items: sidebars.sidebarReference, }, + { + type: "category", + label: "Development Guide", + collapsed: true, + collapsible: true, + items: sidebars.sidebarDevelopmentGuide, + }, { type: "category", label: "Help", diff --git a/docs/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.js b/docs/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.js index dafe9d0f1..6cebc6002 100644 --- a/docs/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.js +++ b/docs/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.js @@ -1,10 +1,11 @@ -import React from 'react'; +import React, {useState, useRef, useEffect} from 'react'; import clsx from 'clsx'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import {useAlternatePageUtils} from '@docusaurus/theme-common/internal'; +import {useCollapsible, Collapsible} from '@docusaurus/theme-common'; import {translate} from '@docusaurus/Translate'; import {useLocation} from '@docusaurus/router'; -import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem'; + const localeFlags = { en: '🇺🇸', @@ -30,6 +31,112 @@ function renderLocaleNode(locale, localeConfigs) { ); } +function LocaleDropdownDesktop({currentLocale, localeConfigs, localeItems, className}) { + const [isOpen, setIsOpen] = useState(false); + const closeTimerRef = useRef(null); + + function handleMouseEnter() { + if (closeTimerRef.current) { + clearTimeout(closeTimerRef.current); + closeTimerRef.current = null; + } + setIsOpen(true); + } + + function handleMouseLeave() { + // 短暂延迟关闭,让鼠标有时间移动到下拉菜单上 + closeTimerRef.current = setTimeout(() => { + setIsOpen(false); + }, 100); + } + + useEffect(() => { + return () => { + if (closeTimerRef.current) { + clearTimeout(closeTimerRef.current); + } + }; + }, []); + + return ( +