consultant-agent 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,29 @@
1
+ # 更新日志
2
+
3
+ ## [0.1.0] - 2024-07-08
4
+
5
+ ### 新增
6
+ - 🎉 首次发布
7
+ - ✨ 核心 Agent 功能
8
+ - 天气查询
9
+ - 数学计算
10
+ - 联网搜索
11
+ - 网页抓取
12
+ - 📄 文档处理
13
+ - PDF 阅读
14
+ - Word 阅读
15
+ - Excel 阅读
16
+ - PPT 阅读
17
+ - 📊 分析功能
18
+ - 内容总结
19
+ - 报告大纲生成
20
+ - 竞品对比
21
+ - 案例搜索
22
+ - 🖥️ 命令行工具
23
+ - `consultant` 交互式对话
24
+ - `consultant ask` 单次提问
25
+ - `consultant clear` 清空记忆
26
+ - 🔧 开发者 API
27
+ - `ConsultantAgent` 类
28
+ - `as_tool()` 方法,可嵌入其他 Agent
29
+ - 💾 对话记忆功能
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 xiaoboluo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,195 @@
1
+ Metadata-Version: 2.4
2
+ Name: consultant-agent
3
+ Version: 0.1.0
4
+ Summary: 一个专业的咨询顾问 AI Agent,支持文档分析、联网搜索、报告生成
5
+ Project-URL: Homepage, https://github.com/xiaoboluo/consultant-agent
6
+ Project-URL: Repository, https://github.com/xiaoboluo/consultant-agent
7
+ Author-email: xiaoboluo <your@email.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: agent,ai,consultant,langchain,llm
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Requires-Python: >=3.10
19
+ Requires-Dist: beautifulsoup4>=4.12.0
20
+ Requires-Dist: ddgs>=6.0.0
21
+ Requires-Dist: langchain-openai>=0.1.0
22
+ Requires-Dist: langchain>=0.2.0
23
+ Requires-Dist: langgraph>=0.1.0
24
+ Requires-Dist: openpyxl>=3.1.0
25
+ Requires-Dist: pandas>=2.0.0
26
+ Requires-Dist: pdfplumber>=0.10.0
27
+ Requires-Dist: python-docx>=1.0.0
28
+ Requires-Dist: python-pptx>=0.6.0
29
+ Requires-Dist: requests>=2.31.0
30
+ Provides-Extra: dev
31
+ Requires-Dist: black>=24.0.0; extra == 'dev'
32
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
33
+ Requires-Dist: ruff>=0.3.0; extra == 'dev'
34
+ Provides-Extra: ocr
35
+ Requires-Dist: pillow>=10.0.0; extra == 'ocr'
36
+ Requires-Dist: pymupdf>=1.23.0; extra == 'ocr'
37
+ Requires-Dist: pytesseract>=0.3.10; extra == 'ocr'
38
+ Provides-Extra: web
39
+ Requires-Dist: fastapi>=0.110.0; extra == 'web'
40
+ Requires-Dist: gradio>=4.0.0; extra == 'web'
41
+ Requires-Dist: uvicorn>=0.27.0; extra == 'web'
42
+ Description-Content-Type: text/markdown
43
+
44
+ # Consultant Agent 🤖
45
+
46
+ 一个专业的咨询顾问 AI Agent,一行命令安装,开箱即用。
47
+
48
+ [![PyPI version](https://badge.fury.io/py/consultant-agent.svg)](https://pypi.org/project/consultant-agent/)
49
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
50
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
51
+
52
+ ## ✨ 特性
53
+
54
+ - 🔍 **联网搜索** - 实时获取最新信息
55
+ - 📄 **文档阅读** - 支持 PDF、Word、Excel、PPT
56
+ - 📊 **数据分析** - Excel 数据处理与分析
57
+ - 📝 **内容生成** - 报告大纲、竞品对比、内容总结
58
+ - 🛠️ **易于集成** - 可作为工具嵌入其他 Agent
59
+ - 💾 **对话记忆** - 自动保存上下文
60
+
61
+ ## 🚀 快速开始
62
+
63
+ ### 安装
64
+
65
+ ```bash
66
+ pip install consultant-agent
67
+ ```
68
+
69
+ ### 设置 API Key
70
+
71
+ ```bash
72
+ # Linux/Mac
73
+ export DEEPSEEK_API_KEY="sk-your-api-key"
74
+
75
+ # Windows
76
+ set DEEPSEEK_API_KEY=sk-your-api-key
77
+ ```
78
+
79
+ > 💡 去 [DeepSeek 开放平台](https://platform.deepseek.com/) 获取 API Key
80
+
81
+ ### 使用
82
+
83
+ **命令行交互**
84
+ ```bash
85
+ consultant
86
+ ```
87
+
88
+ **单次提问**
89
+ ```bash
90
+ consultant ask "北京今天天气怎么样"
91
+ consultant ask "帮我生成一个 AI Agent 技术发展的报告大纲"
92
+ ```
93
+
94
+ **Python 代码**
95
+ ```python
96
+ from consultant_agent import ConsultantAgent
97
+
98
+ agent = ConsultantAgent()
99
+ reply = agent.ask("分析一下新能源汽车行业趋势")
100
+ print(reply)
101
+ ```
102
+
103
+ ## 📖 功能详解
104
+
105
+ ### 命令行命令
106
+
107
+ | 命令 | 说明 | 示例 |
108
+ |------|------|------|
109
+ | `consultant` | 交互式对话 | - |
110
+ | `consultant ask "问题"` | 单次提问 | `consultant ask "上海天气"` |
111
+ | `consultant clear` | 清空记忆 | - |
112
+
113
+ ### Python API
114
+
115
+ ```python
116
+ from consultant_agent import ConsultantAgent
117
+
118
+ # 基础用法
119
+ agent = ConsultantAgent()
120
+ reply = agent.ask("你的问题")
121
+
122
+ # 自定义配置
123
+ agent = ConsultantAgent(
124
+ api_key="sk-xxx", # 可选,默认从环境变量读取
125
+ model="deepseek-chat", # 模型名称
126
+ temperature=0, # 温度参数
127
+ enable_memory=True, # 启用记忆
128
+ )
129
+
130
+ # 清空记忆
131
+ agent.clear_memory()
132
+ ```
133
+
134
+ ### 作为工具嵌入其他 Agent
135
+
136
+ ```python
137
+ from consultant_agent import ConsultantAgent
138
+ from langgraph.prebuilt import create_react_agent
139
+
140
+ # 创建咨询顾问
141
+ consultant = ConsultantAgent()
142
+
143
+ # 转换为工具
144
+ consultant_tool = consultant.as_tool()
145
+
146
+ # 在你的 Agent 中使用
147
+ your_agent = create_react_agent(
148
+ your_llm,
149
+ tools=[consultant_tool, your_other_tools...]
150
+ )
151
+ ```
152
+
153
+ ## 🎯 支持的功能
154
+
155
+ | 功能 | 说明 | 示例 |
156
+ |------|------|------|
157
+ | 天气查询 | 全球城市天气 | "北京天气" |
158
+ | 数学计算 | 表达式计算 | "计算 123 * 456" |
159
+ | 联网搜索 | DuckDuckGo 搜索 | "搜索 AI Agent 最新进展" |
160
+ | 网页抓取 | 读取网页内容 | "读取 https://example.com" |
161
+ | PDF 阅读 | 提取 PDF 文字 | "读取 report.pdf" |
162
+ | Word 阅读 | 读取 docx 文档 | "读取 document.docx" |
163
+ | Excel 阅读 | 读取表格数据 | "读取 data.xlsx" |
164
+ | PPT 阅读 | 提取幻灯片文字 | "读取 slides.pptx" |
165
+ | 内容总结 | 多种总结风格 | "总结这篇文章" |
166
+ | 报告大纲 | 生成专业大纲 | "生成 XX 报告大纲" |
167
+ | 竞品对比 | 多维度对比表 | "对比 A、B、C 产品" |
168
+ | 案例搜索 | 查找行业案例 | "搜索数字化转型案例" |
169
+
170
+ ## ⚙️ 环境变量
171
+
172
+ | 变量 | 必须 | 说明 |
173
+ |------|------|------|
174
+ | `DEEPSEEK_API_KEY` | ✅ | DeepSeek API Key |
175
+
176
+ ## 📦 可选依赖
177
+
178
+ ```bash
179
+ # OCR 功能(识别图片/PDF 中的文字)
180
+ pip install consultant-agent[ocr]
181
+
182
+ # Web 界面
183
+ pip install consultant-agent[web]
184
+
185
+ # 完整安装
186
+ pip install consultant-agent[ocr,web]
187
+ ```
188
+
189
+ ## 🤝 贡献
190
+
191
+ 欢迎 Issue 和 PR!
192
+
193
+ ## 📄 许可证
194
+
195
+ MIT License
@@ -0,0 +1,152 @@
1
+ # Consultant Agent 🤖
2
+
3
+ 一个专业的咨询顾问 AI Agent,一行命令安装,开箱即用。
4
+
5
+ [![PyPI version](https://badge.fury.io/py/consultant-agent.svg)](https://pypi.org/project/consultant-agent/)
6
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ## ✨ 特性
10
+
11
+ - 🔍 **联网搜索** - 实时获取最新信息
12
+ - 📄 **文档阅读** - 支持 PDF、Word、Excel、PPT
13
+ - 📊 **数据分析** - Excel 数据处理与分析
14
+ - 📝 **内容生成** - 报告大纲、竞品对比、内容总结
15
+ - 🛠️ **易于集成** - 可作为工具嵌入其他 Agent
16
+ - 💾 **对话记忆** - 自动保存上下文
17
+
18
+ ## 🚀 快速开始
19
+
20
+ ### 安装
21
+
22
+ ```bash
23
+ pip install consultant-agent
24
+ ```
25
+
26
+ ### 设置 API Key
27
+
28
+ ```bash
29
+ # Linux/Mac
30
+ export DEEPSEEK_API_KEY="sk-your-api-key"
31
+
32
+ # Windows
33
+ set DEEPSEEK_API_KEY=sk-your-api-key
34
+ ```
35
+
36
+ > 💡 去 [DeepSeek 开放平台](https://platform.deepseek.com/) 获取 API Key
37
+
38
+ ### 使用
39
+
40
+ **命令行交互**
41
+ ```bash
42
+ consultant
43
+ ```
44
+
45
+ **单次提问**
46
+ ```bash
47
+ consultant ask "北京今天天气怎么样"
48
+ consultant ask "帮我生成一个 AI Agent 技术发展的报告大纲"
49
+ ```
50
+
51
+ **Python 代码**
52
+ ```python
53
+ from consultant_agent import ConsultantAgent
54
+
55
+ agent = ConsultantAgent()
56
+ reply = agent.ask("分析一下新能源汽车行业趋势")
57
+ print(reply)
58
+ ```
59
+
60
+ ## 📖 功能详解
61
+
62
+ ### 命令行命令
63
+
64
+ | 命令 | 说明 | 示例 |
65
+ |------|------|------|
66
+ | `consultant` | 交互式对话 | - |
67
+ | `consultant ask "问题"` | 单次提问 | `consultant ask "上海天气"` |
68
+ | `consultant clear` | 清空记忆 | - |
69
+
70
+ ### Python API
71
+
72
+ ```python
73
+ from consultant_agent import ConsultantAgent
74
+
75
+ # 基础用法
76
+ agent = ConsultantAgent()
77
+ reply = agent.ask("你的问题")
78
+
79
+ # 自定义配置
80
+ agent = ConsultantAgent(
81
+ api_key="sk-xxx", # 可选,默认从环境变量读取
82
+ model="deepseek-chat", # 模型名称
83
+ temperature=0, # 温度参数
84
+ enable_memory=True, # 启用记忆
85
+ )
86
+
87
+ # 清空记忆
88
+ agent.clear_memory()
89
+ ```
90
+
91
+ ### 作为工具嵌入其他 Agent
92
+
93
+ ```python
94
+ from consultant_agent import ConsultantAgent
95
+ from langgraph.prebuilt import create_react_agent
96
+
97
+ # 创建咨询顾问
98
+ consultant = ConsultantAgent()
99
+
100
+ # 转换为工具
101
+ consultant_tool = consultant.as_tool()
102
+
103
+ # 在你的 Agent 中使用
104
+ your_agent = create_react_agent(
105
+ your_llm,
106
+ tools=[consultant_tool, your_other_tools...]
107
+ )
108
+ ```
109
+
110
+ ## 🎯 支持的功能
111
+
112
+ | 功能 | 说明 | 示例 |
113
+ |------|------|------|
114
+ | 天气查询 | 全球城市天气 | "北京天气" |
115
+ | 数学计算 | 表达式计算 | "计算 123 * 456" |
116
+ | 联网搜索 | DuckDuckGo 搜索 | "搜索 AI Agent 最新进展" |
117
+ | 网页抓取 | 读取网页内容 | "读取 https://example.com" |
118
+ | PDF 阅读 | 提取 PDF 文字 | "读取 report.pdf" |
119
+ | Word 阅读 | 读取 docx 文档 | "读取 document.docx" |
120
+ | Excel 阅读 | 读取表格数据 | "读取 data.xlsx" |
121
+ | PPT 阅读 | 提取幻灯片文字 | "读取 slides.pptx" |
122
+ | 内容总结 | 多种总结风格 | "总结这篇文章" |
123
+ | 报告大纲 | 生成专业大纲 | "生成 XX 报告大纲" |
124
+ | 竞品对比 | 多维度对比表 | "对比 A、B、C 产品" |
125
+ | 案例搜索 | 查找行业案例 | "搜索数字化转型案例" |
126
+
127
+ ## ⚙️ 环境变量
128
+
129
+ | 变量 | 必须 | 说明 |
130
+ |------|------|------|
131
+ | `DEEPSEEK_API_KEY` | ✅ | DeepSeek API Key |
132
+
133
+ ## 📦 可选依赖
134
+
135
+ ```bash
136
+ # OCR 功能(识别图片/PDF 中的文字)
137
+ pip install consultant-agent[ocr]
138
+
139
+ # Web 界面
140
+ pip install consultant-agent[web]
141
+
142
+ # 完整安装
143
+ pip install consultant-agent[ocr,web]
144
+ ```
145
+
146
+ ## 🤝 贡献
147
+
148
+ 欢迎 Issue 和 PR!
149
+
150
+ ## 📄 许可证
151
+
152
+ MIT License
@@ -0,0 +1,77 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "consultant-agent"
7
+ version = "0.1.0"
8
+ description = "一个专业的咨询顾问 AI Agent,支持文档分析、联网搜索、报告生成"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "xiaoboluo", email = "your@email.com" }
14
+ ]
15
+ keywords = ["ai", "agent", "langchain", "consultant", "llm"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ ]
25
+
26
+ dependencies = [
27
+ "langchain>=0.2.0",
28
+ "langchain-openai>=0.1.0",
29
+ "langgraph>=0.1.0",
30
+ "requests>=2.31.0",
31
+ "ddgs>=6.0.0",
32
+ "beautifulsoup4>=4.12.0",
33
+ "pdfplumber>=0.10.0",
34
+ "python-docx>=1.0.0",
35
+ "python-pptx>=0.6.0",
36
+ "pandas>=2.0.0",
37
+ "openpyxl>=3.1.0",
38
+ ]
39
+
40
+ [project.optional-dependencies]
41
+ ocr = [
42
+ "pytesseract>=0.3.10",
43
+ "Pillow>=10.0.0",
44
+ "PyMuPDF>=1.23.0",
45
+ ]
46
+ web = [
47
+ "gradio>=4.0.0",
48
+ "fastapi>=0.110.0",
49
+ "uvicorn>=0.27.0",
50
+ ]
51
+ dev = [
52
+ "pytest>=8.0.0",
53
+ "black>=24.0.0",
54
+ "ruff>=0.3.0",
55
+ ]
56
+
57
+ # 命令行入口
58
+ [project.scripts]
59
+ consultant = "consultant_agent.cli:main"
60
+
61
+ [project.urls]
62
+ Homepage = "https://github.com/xiaoboluo/consultant-agent"
63
+ Repository = "https://github.com/xiaoboluo/consultant-agent"
64
+
65
+ [tool.hatch.build.targets.wheel]
66
+ packages = ["src/consultant_agent"]
67
+
68
+ [tool.hatch.build.targets.sdist]
69
+ exclude = [
70
+ "venv",
71
+ ".venv",
72
+ "__pycache__",
73
+ "*.pyc",
74
+ ".git",
75
+ "dist",
76
+ "build",
77
+ ]
@@ -0,0 +1,15 @@
1
+ """
2
+ Consultant Agent - 专业的咨询顾问 AI Agent
3
+
4
+ 快速开始:
5
+ from consultant_agent import ConsultantAgent
6
+
7
+ agent = ConsultantAgent(api_key="sk-xxx")
8
+ reply = agent.ask("帮我分析新能源汽车行业")
9
+ print(reply)
10
+ """
11
+
12
+ from consultant_agent.agent import ConsultantAgent
13
+ from consultant_agent.version import __version__
14
+
15
+ __all__ = ["ConsultantAgent", "__version__"]
@@ -0,0 +1,178 @@
1
+ """
2
+ ConsultantAgent - 核心 Agent 类
3
+
4
+ 可以独立使用,也可以作为工具嵌入其他 Agent。
5
+ """
6
+
7
+ import os
8
+ import json
9
+ from datetime import datetime
10
+ from typing import Optional
11
+ from langchain_openai import ChatOpenAI
12
+ from langchain_core.tools import tool
13
+ from langgraph.prebuilt import create_react_agent
14
+
15
+ from consultant_agent.tools import get_all_tools
16
+
17
+
18
+ class ConsultantAgent:
19
+ """
20
+ 咨询顾问 AI Agent
21
+
22
+ Example:
23
+ >>> agent = ConsultantAgent(api_key="sk-xxx")
24
+ >>> reply = agent.ask("北京今天天气怎么样")
25
+ >>> print(reply)
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ api_key: Optional[str] = None,
31
+ model: str = "deepseek-chat",
32
+ base_url: str = "https://api.deepseek.com",
33
+ temperature: float = 0,
34
+ memory_file: Optional[str] = None,
35
+ enable_memory: bool = True,
36
+ ):
37
+ """
38
+ 初始化 Agent
39
+
40
+ Args:
41
+ api_key: DeepSeek API Key,不传则从环境变量 DEEPSEEK_API_KEY 读取
42
+ model: 模型名称
43
+ base_url: API 地址
44
+ temperature: 温度参数
45
+ memory_file: 记忆文件路径,None 则使用默认路径
46
+ enable_memory: 是否启用记忆功能
47
+ """
48
+ # API Key
49
+ self.api_key = api_key or os.environ.get("DEEPSEEK_API_KEY")
50
+ if not self.api_key:
51
+ raise ValueError(
52
+ "需要提供 api_key 或设置环境变量 DEEPSEEK_API_KEY\n"
53
+ "export DEEPSEEK_API_KEY='sk-xxx'"
54
+ )
55
+
56
+ # LLM
57
+ self.llm = ChatOpenAI(
58
+ model=model,
59
+ base_url=base_url,
60
+ api_key=self.api_key,
61
+ temperature=temperature,
62
+ )
63
+
64
+ # 记忆
65
+ self.enable_memory = enable_memory
66
+ if memory_file:
67
+ self.memory_file = memory_file
68
+ else:
69
+ home = os.path.expanduser("~")
70
+ self.memory_file = os.path.join(home, ".consultant_agent", "memory.json")
71
+
72
+ # 确保目录存在
73
+ os.makedirs(os.path.dirname(self.memory_file), exist_ok=True)
74
+
75
+ # 工具
76
+ self.tools = get_all_tools(self.llm)
77
+
78
+ # System Prompt
79
+ self.system_prompt = """你是一个专业的咨询顾问 AI 助手。
80
+
81
+ 你的能力:
82
+ - 查询天气、计算数学
83
+ - 联网搜索最新信息
84
+ - 读取文档(PDF、Word、Excel、PPT)
85
+ - 总结分析内容、生成报告大纲
86
+ - 竞品对比分析
87
+
88
+ 请用中文回答,保持专业、简洁。
89
+ """
90
+
91
+ # 创建 Agent
92
+ self._agent = create_react_agent(
93
+ self.llm,
94
+ self.tools,
95
+ prompt=self.system_prompt,
96
+ )
97
+
98
+ def ask(self, question: str) -> str:
99
+ """
100
+ 向 Agent 提问
101
+
102
+ Args:
103
+ question: 问题或任务
104
+
105
+ Returns:
106
+ Agent 的回复
107
+ """
108
+ # 加载记忆
109
+ memory = self._load_memory() if self.enable_memory else []
110
+
111
+ # 构建消息
112
+ messages = []
113
+ for msg in memory:
114
+ messages.append((msg["role"], msg["content"]))
115
+ messages.append(("user", question))
116
+
117
+ # 调用 Agent
118
+ result = self._agent.invoke({"messages": messages})
119
+ reply = result["messages"][-1].content
120
+
121
+ # 保存记忆
122
+ if self.enable_memory:
123
+ memory.append({"role": "user", "content": question})
124
+ memory.append({"role": "assistant", "content": reply})
125
+ self._save_memory(memory)
126
+
127
+ return reply
128
+
129
+ def clear_memory(self):
130
+ """清空记忆"""
131
+ self._save_memory([])
132
+
133
+ def as_tool(self):
134
+ """
135
+ 将 Agent 转换为 LangChain Tool,可嵌入其他 Agent
136
+
137
+ Example:
138
+ >>> consultant = ConsultantAgent(api_key="sk-xxx")
139
+ >>> tool = consultant.as_tool()
140
+ >>> # 在其他 Agent 中使用
141
+ >>> other_agent = create_react_agent(llm, [tool, ...])
142
+ """
143
+
144
+ @tool
145
+ def consultant_agent(question: str) -> str:
146
+ """
147
+ 向咨询顾问 Agent 提问。擅长:
148
+ - 读取文档(PDF/Word/Excel/PPT)
149
+ - 联网搜索最新信息
150
+ - 生成报告大纲、竞品分析
151
+ - 内容总结分析
152
+
153
+ Args:
154
+ question: 问题或任务描述
155
+ """
156
+ return self.ask(question)
157
+
158
+ return consultant_agent
159
+
160
+ def _load_memory(self) -> list:
161
+ """加载记忆"""
162
+ if os.path.exists(self.memory_file):
163
+ try:
164
+ with open(self.memory_file, "r", encoding="utf-8") as f:
165
+ data = json.load(f)
166
+ return data.get("messages", [])[-100:] # 最多保留 100 条
167
+ except:
168
+ pass
169
+ return []
170
+
171
+ def _save_memory(self, messages: list):
172
+ """保存记忆"""
173
+ data = {
174
+ "messages": messages[-100:], # 最多保留 100 条
175
+ "updated_at": datetime.now().isoformat(),
176
+ }
177
+ with open(self.memory_file, "w", encoding="utf-8") as f:
178
+ json.dump(data, f, ensure_ascii=False, indent=2)
@@ -0,0 +1,128 @@
1
+ """
2
+ 命令行入口
3
+
4
+ 用法:
5
+ consultant # 交互式对话
6
+ consultant ask "问题" # 单次提问
7
+ consultant web # 启动 Web 界面
8
+ """
9
+
10
+ import argparse
11
+ import sys
12
+ import os
13
+
14
+
15
+ def main():
16
+ parser = argparse.ArgumentParser(
17
+ prog="consultant",
18
+ description="咨询顾问 AI Agent - 专业的文档分析和报告生成助手",
19
+ )
20
+ subparsers = parser.add_subparsers(dest="command", help="可用命令")
21
+
22
+ # ask 命令
23
+ ask_parser = subparsers.add_parser("ask", help="单次提问")
24
+ ask_parser.add_argument("question", help="问题内容")
25
+
26
+ # web 命令
27
+ web_parser = subparsers.add_parser("web", help="启动 Web 界面")
28
+ web_parser.add_argument("--port", type=int, default=7860, help="端口号")
29
+ web_parser.add_argument("--share", action="store_true", help="生成公网链接")
30
+
31
+ # clear 命令
32
+ clear_parser = subparsers.add_parser("clear", help="清空记忆")
33
+
34
+ args = parser.parse_args()
35
+
36
+ # 检查 API Key
37
+ api_key = os.environ.get("DEEPSEEK_API_KEY")
38
+ if not api_key:
39
+ print("❌ 错误:请设置环境变量 DEEPSEEK_API_KEY")
40
+ print("")
41
+ print(" export DEEPSEEK_API_KEY='sk-xxx'")
42
+ print("")
43
+ sys.exit(1)
44
+
45
+ if args.command == "ask":
46
+ # 单次提问
47
+ from consultant_agent import ConsultantAgent
48
+
49
+ agent = ConsultantAgent(api_key=api_key)
50
+ print(agent.ask(args.question))
51
+
52
+ elif args.command == "web":
53
+ # 启动 Web 界面
54
+ try:
55
+ from consultant_agent.web import launch_web
56
+ launch_web(port=args.port, share=args.share)
57
+ except ImportError:
58
+ print("❌ 需要安装 web 依赖:")
59
+ print(" pip install consultant-agent[web]")
60
+ sys.exit(1)
61
+
62
+ elif args.command == "clear":
63
+ # 清空记忆
64
+ from consultant_agent import ConsultantAgent
65
+
66
+ agent = ConsultantAgent(api_key=api_key)
67
+ agent.clear_memory()
68
+ print("✅ 记忆已清空")
69
+
70
+ else:
71
+ # 交互式对话
72
+ interactive_mode(api_key)
73
+
74
+
75
+ def interactive_mode(api_key: str):
76
+ """交互式对话模式"""
77
+ from consultant_agent import ConsultantAgent
78
+
79
+ print("=" * 50)
80
+ print("🤖 咨询顾问 Agent")
81
+ print("=" * 50)
82
+ print("输入问题开始对话,输入 'quit' 退出")
83
+ print("=" * 50)
84
+ print("")
85
+
86
+ agent = ConsultantAgent(api_key=api_key)
87
+
88
+ while True:
89
+ try:
90
+ user_input = input("你: ").strip()
91
+
92
+ if not user_input:
93
+ continue
94
+
95
+ if user_input.lower() in ["quit", "exit", "退出", "bye"]:
96
+ print("👋 再见!")
97
+ break
98
+
99
+ if user_input == "/clear":
100
+ agent.clear_memory()
101
+ print("✅ 记忆已清空\n")
102
+ continue
103
+
104
+ if user_input == "/help":
105
+ print("""
106
+ 可用命令:
107
+ /clear - 清空对话记忆
108
+ /help - 显示帮助
109
+ quit - 退出程序
110
+
111
+ 或者直接输入问题开始对话!
112
+ """)
113
+ continue
114
+
115
+ # 调用 Agent
116
+ print("思考中...")
117
+ reply = agent.ask(user_input)
118
+ print(f"\n助手: {reply}\n")
119
+
120
+ except KeyboardInterrupt:
121
+ print("\n👋 再见!")
122
+ break
123
+ except Exception as e:
124
+ print(f"❌ 出错了:{e}\n")
125
+
126
+
127
+ if __name__ == "__main__":
128
+ main()
@@ -0,0 +1,21 @@
1
+ """
2
+ 工具集合
3
+ """
4
+
5
+ from consultant_agent.tools.basic import get_basic_tools
6
+ from consultant_agent.tools.search import get_search_tools
7
+ from consultant_agent.tools.document import get_document_tools
8
+ from consultant_agent.tools.analysis import get_analysis_tools
9
+
10
+
11
+ def get_all_tools(llm=None):
12
+ """获取所有工具"""
13
+ tools = []
14
+ tools.extend(get_basic_tools())
15
+ tools.extend(get_search_tools())
16
+ tools.extend(get_document_tools())
17
+ tools.extend(get_analysis_tools(llm))
18
+ return tools
19
+
20
+
21
+ __all__ = ["get_all_tools"]
@@ -0,0 +1,111 @@
1
+ """
2
+ 分析工具:总结、报告大纲、竞品对比
3
+ """
4
+
5
+ from langchain_core.tools import tool
6
+
7
+
8
+ def get_analysis_tools(llm=None):
9
+ """获取分析工具列表,需要传入 LLM 实例"""
10
+
11
+ if llm is None:
12
+ return []
13
+
14
+ @tool
15
+ def summarize(content: str, style: str = "要点") -> str:
16
+ """
17
+ 总结归纳内容。
18
+ content: 需要总结的文本
19
+ style: 总结风格 - "要点"(3-5个要点)、"简述"(一段话)、"详细"(分层次)
20
+ """
21
+ style_prompts = {
22
+ "要点": "请将以下内容总结为3-5个核心要点:",
23
+ "简述": "请用一段话(100字以内)概括以下内容:",
24
+ "详细": "请对以下内容进行分层次的详细总结:",
25
+ }
26
+
27
+ prompt = style_prompts.get(style, style_prompts["要点"])
28
+
29
+ try:
30
+ if len(content) > 6000:
31
+ content = content[:6000] + "..."
32
+
33
+ response = llm.invoke([("user", f"{prompt}\n\n{content}")])
34
+ return f"📋 总结({style}模式):\n\n{response.content}"
35
+ except Exception as e:
36
+ return f"总结失败:{e}"
37
+
38
+ @tool
39
+ def generate_outline(topic: str, report_type: str = "分析报告") -> str:
40
+ """
41
+ 根据主题生成报告大纲。
42
+ topic: 报告主题
43
+ report_type: 报告类型 - "分析报告"、"研究报告"、"咨询方案"
44
+ """
45
+ prompt = f"""请为主题「{topic}」设计一个专业的{report_type}大纲框架。
46
+
47
+ 要求:
48
+ 1. 包含一级和二级标题
49
+ 2. 每个部分简要说明应包含的内容
50
+ 3. 逻辑严谨,结构完整"""
51
+
52
+ try:
53
+ response = llm.invoke([("user", prompt)])
54
+ return f"📑 报告大纲 - {topic}\n\n{response.content}"
55
+ except Exception as e:
56
+ return f"生成大纲失败:{e}"
57
+
58
+ @tool
59
+ def generate_comparison(topic: str, products: str, dimensions: str = "") -> str:
60
+ """
61
+ 生成竞品对比表。
62
+ topic: 对比主题
63
+ products: 要对比的产品,逗号分隔
64
+ dimensions: 对比维度,逗号分隔(可选)
65
+ """
66
+ prompt = f"""请生成一份专业的竞品对比表。
67
+
68
+ 对比主题:{topic}
69
+ 对比产品:{products}
70
+ 对比维度:{dimensions if dimensions else "请根据主题自动选择5-8个关键维度"}
71
+
72
+ 要求:
73
+ 1. 使用 Markdown 表格格式
74
+ 2. 内容具体、有数据支撑
75
+ 3. 在表格后添加对比总结(3-5个要点)"""
76
+
77
+ try:
78
+ response = llm.invoke([("user", prompt)])
79
+ return f"📊 竞品对比 - {topic}\n\n{response.content}"
80
+ except Exception as e:
81
+ return f"生成对比表失败:{e}"
82
+
83
+ @tool
84
+ def search_cases(topic: str, industry: str = "") -> str:
85
+ """
86
+ 搜索相关案例。
87
+ topic: 案例主题
88
+ industry: 行业领域(可选)
89
+ """
90
+ try:
91
+ from ddgs import DDGS
92
+
93
+ search_query = f"{topic} 案例 成功 企业 {industry}".strip()
94
+
95
+ with DDGS() as ddgs:
96
+ results = list(ddgs.text(search_query, max_results=5))
97
+
98
+ if not results:
99
+ return f"未找到关于 '{topic}' 的案例"
100
+
101
+ output = [f"🔍 案例搜索:{topic}"]
102
+ for i, r in enumerate(results, 1):
103
+ output.append(f"\n案例 {i}:{r['title']}")
104
+ output.append(f"来源:{r['href']}")
105
+ output.append(f"摘要:{r['body'][:200]}...")
106
+
107
+ return "\n".join(output)
108
+ except Exception as e:
109
+ return f"案例搜索失败:{e}"
110
+
111
+ return [summarize, generate_outline, generate_comparison, search_cases]
@@ -0,0 +1,45 @@
1
+ """
2
+ 基础工具:天气、计算
3
+ """
4
+
5
+ import requests
6
+ from langchain_core.tools import tool
7
+
8
+
9
+ @tool
10
+ def get_weather(city: str) -> str:
11
+ """查询指定城市的天气。传入城市名称(中文或英文)。"""
12
+ try:
13
+ url = f"https://wttr.in/{city}?format=j1"
14
+ response = requests.get(url, timeout=10)
15
+ data = response.json()
16
+
17
+ current = data["current_condition"][0]
18
+ weather_desc = current.get("lang_zh", [{}])[0].get(
19
+ "value", current["weatherDesc"][0]["value"]
20
+ )
21
+ temp = current["temp_C"]
22
+ humidity = current["humidity"]
23
+ wind = current["windspeedKmph"]
24
+
25
+ return f"{city}天气:{weather_desc},温度 {temp}°C,湿度 {humidity}%,风速 {wind}km/h"
26
+ except Exception as e:
27
+ return f"查询天气失败:{e}"
28
+
29
+
30
+ @tool
31
+ def calculate(expression: str) -> str:
32
+ """计算数学表达式。例如:'2+3*4' 或 '100/5' 或 '2**10'"""
33
+ try:
34
+ allowed = set("0123456789+-*/.() ")
35
+ if not all(c in allowed for c in expression):
36
+ return "只支持数学运算"
37
+ result = eval(expression)
38
+ return f"{expression} = {result}"
39
+ except Exception as e:
40
+ return f"计算出错:{e}"
41
+
42
+
43
+ def get_basic_tools():
44
+ """获取基础工具列表"""
45
+ return [get_weather, calculate]
@@ -0,0 +1,216 @@
1
+ """
2
+ 文档工具:读取 PDF/Word/Excel/PPT
3
+ """
4
+
5
+ import os
6
+ from langchain_core.tools import tool
7
+
8
+
9
+ @tool
10
+ def read_file(file_path: str) -> str:
11
+ """读取本地文本文件内容。传入文件的完整路径。"""
12
+ try:
13
+ full_path = os.path.abspath(os.path.expanduser(file_path))
14
+
15
+ if not os.path.exists(full_path):
16
+ return f"文件不存在:{full_path}"
17
+
18
+ with open(full_path, "r", encoding="utf-8") as f:
19
+ content = f.read()
20
+
21
+ if len(content) > 5000:
22
+ return f"文件内容(前5000字):\n{content[:5000]}..."
23
+ return f"文件内容:\n{content}"
24
+ except Exception as e:
25
+ return f"读取失败:{e}"
26
+
27
+
28
+ @tool
29
+ def read_pdf(file_path: str, max_pages: int = 50) -> str:
30
+ """
31
+ 读取PDF文件内容。
32
+ file_path: PDF文件路径
33
+ max_pages: 最多读取的页数,默认50页
34
+ """
35
+ try:
36
+ import pdfplumber
37
+
38
+ full_path = os.path.abspath(os.path.expanduser(file_path))
39
+
40
+ if not os.path.exists(full_path):
41
+ return f"文件不存在:{full_path}"
42
+
43
+ text_parts = []
44
+
45
+ with pdfplumber.open(full_path) as pdf:
46
+ total_pages = len(pdf.pages)
47
+ pages_to_read = min(max_pages, total_pages) if max_pages > 0 else total_pages
48
+
49
+ for i, page in enumerate(pdf.pages[:pages_to_read]):
50
+ page_text = page.extract_text()
51
+ if page_text:
52
+ text_parts.append(f"--- 第 {i+1} 页 ---\n{page_text}")
53
+
54
+ content = "\n\n".join(text_parts)
55
+ result = f"📑 PDF文件:{os.path.basename(full_path)}\n📄 共 {total_pages} 页(已读取 {pages_to_read} 页)\n\n{content}"
56
+
57
+ if len(result) > 10000:
58
+ result = result[:10000] + "\n\n...(内容过长,已截断)"
59
+
60
+ return result
61
+
62
+ except Exception as e:
63
+ return f"读取PDF失败:{e}"
64
+
65
+
66
+ @tool
67
+ def read_docx(file_path: str) -> str:
68
+ """读取Word文档(.docx)内容。"""
69
+ try:
70
+ from docx import Document
71
+
72
+ full_path = os.path.abspath(os.path.expanduser(file_path))
73
+
74
+ if not os.path.exists(full_path):
75
+ return f"文件不存在:{full_path}"
76
+
77
+ doc = Document(full_path)
78
+ text_parts = []
79
+
80
+ # 读取段落
81
+ for para in doc.paragraphs:
82
+ if para.text.strip():
83
+ text_parts.append(para.text)
84
+
85
+ # 读取表格
86
+ for table in doc.tables:
87
+ for row in table.rows:
88
+ row_text = " | ".join(cell.text.strip() for cell in row.cells)
89
+ if row_text.strip():
90
+ text_parts.append(row_text)
91
+
92
+ content = "\n\n".join(text_parts)
93
+ result = f"📄 Word文档:{os.path.basename(full_path)}\n\n{content}"
94
+
95
+ if len(result) > 8000:
96
+ result = result[:8000] + "\n\n...(内容过长,已截断)"
97
+
98
+ return result
99
+
100
+ except Exception as e:
101
+ return f"读取Word文档失败:{e}"
102
+
103
+
104
+ @tool
105
+ def read_excel(file_path: str, sheet_name: str = None, max_rows: int = 100) -> str:
106
+ """
107
+ 读取Excel文件内容。
108
+ file_path: Excel文件路径
109
+ sheet_name: 工作表名称,默认读取第一个
110
+ max_rows: 最多读取的行数
111
+ """
112
+ try:
113
+ import pandas as pd
114
+
115
+ full_path = os.path.abspath(os.path.expanduser(file_path))
116
+
117
+ if not os.path.exists(full_path):
118
+ return f"文件不存在:{full_path}"
119
+
120
+ xlsx = pd.ExcelFile(full_path)
121
+ sheet_names = xlsx.sheet_names
122
+
123
+ result = [f"📊 Excel文件:{os.path.basename(full_path)}"]
124
+ result.append(f"📑 工作表:{', '.join(sheet_names)}\n")
125
+
126
+ target_sheet = sheet_name if sheet_name else sheet_names[0]
127
+
128
+ if target_sheet not in sheet_names:
129
+ return f"工作表 '{target_sheet}' 不存在,可用:{', '.join(sheet_names)}"
130
+
131
+ df = pd.read_excel(full_path, sheet_name=target_sheet)
132
+
133
+ total_rows = len(df)
134
+ result.append(f"【{target_sheet}】共 {total_rows} 行 × {len(df.columns)} 列")
135
+ result.append(f"列名:{', '.join(str(col) for col in df.columns)}\n")
136
+
137
+ if total_rows > max_rows:
138
+ df = df.head(max_rows)
139
+ result.append(f"(仅显示前 {max_rows} 行)\n")
140
+
141
+ result.append(df.to_string(index=False))
142
+
143
+ content = "\n".join(result)
144
+ if len(content) > 10000:
145
+ content = content[:10000] + "\n\n...(内容过长,已截断)"
146
+
147
+ return content
148
+
149
+ except Exception as e:
150
+ return f"读取Excel失败:{e}"
151
+
152
+
153
+ @tool
154
+ def read_pptx(file_path: str) -> str:
155
+ """读取PPT文件内容。"""
156
+ try:
157
+ from pptx import Presentation
158
+
159
+ full_path = os.path.abspath(os.path.expanduser(file_path))
160
+
161
+ if not os.path.exists(full_path):
162
+ return f"文件不存在:{full_path}"
163
+
164
+ prs = Presentation(full_path)
165
+ output = [f"📊 PPT文件:{os.path.basename(full_path)}"]
166
+ output.append(f"📄 共 {len(prs.slides)} 页\n")
167
+
168
+ for i, slide in enumerate(prs.slides, 1):
169
+ slide_texts = []
170
+ for shape in slide.shapes:
171
+ if hasattr(shape, "text") and shape.text.strip():
172
+ slide_texts.append(shape.text.strip())
173
+
174
+ output.append(f"\n【第 {i} 页】")
175
+ if slide_texts:
176
+ output.append("\n".join(slide_texts))
177
+ else:
178
+ output.append("(无文字内容)")
179
+
180
+ content = "\n".join(output)
181
+ if len(content) > 8000:
182
+ content = content[:8000] + "\n\n...(内容过长,已截断)"
183
+
184
+ return content
185
+
186
+ except Exception as e:
187
+ return f"读取PPT失败:{e}"
188
+
189
+
190
+ @tool
191
+ def list_files(directory: str) -> str:
192
+ """列出指定目录下的所有文件和文件夹。"""
193
+ try:
194
+ full_path = os.path.abspath(os.path.expanduser(directory))
195
+
196
+ if not os.path.exists(full_path):
197
+ return f"目录不存在:{full_path}"
198
+
199
+ items = os.listdir(full_path)
200
+ if not items:
201
+ return "目录为空"
202
+
203
+ output = []
204
+ for item in sorted(items):
205
+ item_path = os.path.join(full_path, item)
206
+ prefix = "📁" if os.path.isdir(item_path) else "📄"
207
+ output.append(f"{prefix} {item}")
208
+
209
+ return "\n".join(output)
210
+ except Exception as e:
211
+ return f"查看失败:{e}"
212
+
213
+
214
+ def get_document_tools():
215
+ """获取文档工具列表"""
216
+ return [read_file, read_pdf, read_docx, read_excel, read_pptx, list_files]
@@ -0,0 +1,78 @@
1
+ """
2
+ 搜索工具:联网搜索、网页抓取
3
+ """
4
+
5
+ import requests
6
+ from langchain_core.tools import tool
7
+
8
+
9
+ @tool
10
+ def web_search(query: str) -> str:
11
+ """搜索互联网获取最新信息。传入搜索关键词。"""
12
+ try:
13
+ from ddgs import DDGS
14
+
15
+ with DDGS() as ddgs:
16
+ results = list(ddgs.text(query, max_results=5))
17
+
18
+ if not results:
19
+ return f"未找到关于 '{query}' 的结果"
20
+
21
+ output = []
22
+ for i, r in enumerate(results, 1):
23
+ output.append(
24
+ f"{i}. {r['title']}\n 链接:{r['href']}\n 摘要:{r['body'][:150]}..."
25
+ )
26
+
27
+ return "\n\n".join(output)
28
+ except Exception as e:
29
+ return f"搜索失败:{e}"
30
+
31
+
32
+ @tool
33
+ def read_url(url: str) -> str:
34
+ """抓取网页正文内容。传入完整的URL地址。"""
35
+ try:
36
+ from bs4 import BeautifulSoup
37
+
38
+ headers = {
39
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
40
+ }
41
+ response = requests.get(url, headers=headers, timeout=15)
42
+ response.encoding = response.apparent_encoding
43
+
44
+ soup = BeautifulSoup(response.text, "html.parser")
45
+
46
+ # 移除脚本和样式
47
+ for tag in soup(["script", "style", "nav", "header", "footer", "aside"]):
48
+ tag.decompose()
49
+
50
+ # 获取标题
51
+ title = soup.title.string if soup.title else "无标题"
52
+
53
+ # 获取正文
54
+ main_content = soup.find("article") or soup.find("main") or soup.find("body")
55
+
56
+ if main_content:
57
+ paragraphs = main_content.find_all(["p", "h1", "h2", "h3", "h4", "li"])
58
+ text_parts = []
59
+ for p in paragraphs:
60
+ text = p.get_text(strip=True)
61
+ if len(text) > 20:
62
+ text_parts.append(text)
63
+ content = "\n\n".join(text_parts)
64
+ else:
65
+ content = soup.get_text(separator="\n", strip=True)
66
+
67
+ if len(content) > 5000:
68
+ content = content[:5000] + "\n\n...(内容过长,已截断)"
69
+
70
+ return f"📄 标题:{title}\n🔗 来源:{url}\n\n{content}"
71
+
72
+ except Exception as e:
73
+ return f"抓取网页失败:{e}"
74
+
75
+
76
+ def get_search_tools():
77
+ """获取搜索工具列表"""
78
+ return [web_search, read_url]
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1,86 @@
1
+ """
2
+ Gradio Web 界面
3
+
4
+ 用法:
5
+ from consultant_agent.web import launch_web
6
+ launch_web(port=7860)
7
+ """
8
+
9
+ import os
10
+
11
+
12
+ def launch_web(port: int = 7860, share: bool = False):
13
+ """启动 Gradio Web 界面"""
14
+ try:
15
+ import gradio as gr
16
+ except ImportError:
17
+ raise ImportError("需要安装 gradio:pip install consultant-agent[web]")
18
+
19
+ from consultant_agent import ConsultantAgent
20
+
21
+ # 创建 Agent
22
+ api_key = os.environ.get("DEEPSEEK_API_KEY")
23
+ if not api_key:
24
+ raise ValueError("请设置环境变量 DEEPSEEK_API_KEY")
25
+
26
+ agent = ConsultantAgent(api_key=api_key, memory_file=None, enable_memory=False)
27
+
28
+ def chat(message: str, history: list) -> str:
29
+ """Gradio 聊天函数"""
30
+ if not message.strip():
31
+ return ""
32
+
33
+ try:
34
+ # 使用历史构建上下文(简化版,不持久化)
35
+ return agent.ask(message)
36
+ except Exception as e:
37
+ return f"出错了:{e}"
38
+
39
+ # 示例问题
40
+ examples = [
41
+ "北京今天天气怎么样?",
42
+ "计算 123 * 456 + 789",
43
+ "搜索一下 2026年AI Agent发展趋势",
44
+ "帮我生成一个「新能源汽车行业分析」的报告大纲",
45
+ ]
46
+
47
+ # 创建界面
48
+ with gr.Blocks(title="咨询顾问 Agent", theme=gr.themes.Soft()) as demo:
49
+ gr.Markdown("""
50
+ # 🤖 咨询顾问 Agent
51
+
52
+ **能力**:天气查询 | 数学计算 | 联网搜索 | 文档阅读 | 内容总结 | 报告大纲 | 竞品对比
53
+
54
+ ---
55
+ """)
56
+
57
+ chatbot = gr.Chatbot(height=500, show_label=False)
58
+
59
+ with gr.Row():
60
+ msg = gr.Textbox(
61
+ placeholder="输入你的问题...",
62
+ show_label=False,
63
+ scale=9,
64
+ )
65
+ submit_btn = gr.Button("发送", scale=1, variant="primary")
66
+
67
+ with gr.Row():
68
+ clear_btn = gr.Button("🗑️ 清空对话")
69
+
70
+ gr.Examples(examples=examples, inputs=msg, label="💡 试试这些问题")
71
+
72
+ # 绑定事件
73
+ msg.submit(chat, [msg, chatbot], [chatbot]).then(lambda: "", None, msg)
74
+ submit_btn.click(chat, [msg, chatbot], [chatbot]).then(lambda: "", None, msg)
75
+ clear_btn.click(lambda: ([], ""), None, [chatbot, msg])
76
+
77
+ print("=" * 50)
78
+ print("🚀 咨询顾问 Agent Web 服务")
79
+ print("=" * 50)
80
+ print(f"访问地址:http://localhost:{port}")
81
+ if share:
82
+ print("正在生成公网链接...")
83
+ print("按 Ctrl+C 停止服务")
84
+ print("=" * 50)
85
+
86
+ demo.launch(server_name="0.0.0.0", server_port=port, share=share)