310 lines
7.2 KiB
Markdown
310 lines
7.2 KiB
Markdown
# MCP 架构说明
|
||
|
||
## 🎯 MCP 是什么?
|
||
|
||
**MCP (Model Context Protocol)** 是一个**工具调用协议**,它的核心职责是:
|
||
|
||
1. ✅ **定义工具接口**:告诉 LLM 有哪些工具可用,每个工具需要什么参数
|
||
2. ✅ **执行工具调用**:根据请求调用对应的后端 API
|
||
3. ✅ **返回结构化数据**:将 API 结果返回给调用方
|
||
|
||
**MCP 不负责**:
|
||
- ❌ 自然语言理解(NLU)
|
||
- ❌ 意图识别
|
||
- ❌ 结果总结
|
||
- ❌ 对话管理
|
||
|
||
## 📊 当前架构
|
||
|
||
### 方案 1:简单关键词匹配(已实现)
|
||
|
||
```
|
||
用户输入:"查询贵州茅台的股票信息"
|
||
↓
|
||
前端 ChatInterface (关键词匹配)
|
||
↓
|
||
MCP 工具层 (search_china_news)
|
||
↓
|
||
返回 JSON 数据
|
||
↓
|
||
前端显示原始数据
|
||
```
|
||
|
||
**问题**:
|
||
- ✗ 只能识别简单关键词
|
||
- ✗ 无法理解复杂意图
|
||
- ✗ 返回的是原始 JSON,用户体验差
|
||
|
||
### 方案 2:集成 LLM(推荐)
|
||
|
||
```
|
||
用户输入:"查询贵州茅台的股票信息"
|
||
↓
|
||
LLM (Claude/GPT-4/通义千问)
|
||
↓ 理解意图:需要查询股票代码 600519 的基本信息
|
||
↓ 选择工具:get_stock_basic_info
|
||
↓ 提取参数:{"seccode": "600519"}
|
||
MCP 工具层
|
||
↓ 调用 API,获取数据
|
||
返回结构化数据
|
||
↓
|
||
LLM 总结结果
|
||
↓ "贵州茅台(600519)是中国知名的白酒生产企业,
|
||
当前股价 1650.00 元,市值 2.07 万亿..."
|
||
前端显示自然语言回复
|
||
```
|
||
|
||
**优势**:
|
||
- ✓ 理解复杂意图
|
||
- ✓ 自动选择合适的工具
|
||
- ✓ 自然语言总结,用户体验好
|
||
- ✓ 支持多轮对话
|
||
|
||
## 🔧 实现方案
|
||
|
||
### 选项 A:前端集成 LLM(快速实现)
|
||
|
||
**适用场景**:快速原型、小规模应用
|
||
|
||
**优点**:
|
||
- 实现简单
|
||
- 无需修改后端
|
||
|
||
**缺点**:
|
||
- API Key 暴露在前端(安全风险)
|
||
- 每个用户都消耗 API 额度
|
||
- 无法统一管理和监控
|
||
|
||
**实现步骤**:
|
||
|
||
1. 修改 `src/components/ChatBot/ChatInterface.js`:
|
||
|
||
```javascript
|
||
import { llmService } from '../../services/llmService';
|
||
|
||
const handleSendMessage = async () => {
|
||
// ...
|
||
|
||
// 使用 LLM 服务替代简单的 mcpService.chat
|
||
const response = await llmService.chat(inputValue, messages);
|
||
|
||
// ...
|
||
};
|
||
```
|
||
|
||
2. 配置 API Key(在 `.env.local`):
|
||
|
||
```bash
|
||
REACT_APP_OPENAI_API_KEY=sk-xxx...
|
||
# 或者使用通义千问(更便宜)
|
||
REACT_APP_DASHSCOPE_API_KEY=sk-xxx...
|
||
```
|
||
|
||
### 选项 B:后端集成 LLM(生产推荐)⭐
|
||
|
||
**适用场景**:生产环境、需要安全和性能
|
||
|
||
**优点**:
|
||
- ✓ API Key 安全(不暴露给前端)
|
||
- ✓ 统一管理和监控
|
||
- ✓ 可以做缓存优化
|
||
- ✓ 可以做速率限制
|
||
|
||
**缺点**:
|
||
- 需要修改后端
|
||
- 增加服务器成本
|
||
|
||
**实现步骤**:
|
||
|
||
#### 1. 安装依赖
|
||
|
||
```bash
|
||
pip install openai
|
||
```
|
||
|
||
#### 2. 修改 `mcp_server.py`,添加聊天端点
|
||
|
||
在文件末尾添加:
|
||
|
||
```python
|
||
from mcp_chat_endpoint import MCPChatAssistant, ChatRequest, ChatResponse
|
||
|
||
# 创建聊天助手实例
|
||
chat_assistant = MCPChatAssistant(provider="qwen") # 推荐使用通义千问
|
||
|
||
@app.post("/chat", response_model=ChatResponse)
|
||
async def chat_endpoint(request: ChatRequest):
|
||
"""智能对话端点 - 使用LLM理解意图并调用工具"""
|
||
logger.info(f"Chat request: {request.message}")
|
||
|
||
# 获取可用工具列表
|
||
tools = [tool.dict() for tool in TOOLS]
|
||
|
||
# 调用聊天助手
|
||
response = await chat_assistant.chat(
|
||
user_message=request.message,
|
||
conversation_history=request.conversation_history,
|
||
tools=tools,
|
||
)
|
||
|
||
return response
|
||
```
|
||
|
||
#### 3. 配置环境变量
|
||
|
||
在服务器上设置:
|
||
|
||
```bash
|
||
# 方式1:使用通义千问(推荐,价格便宜)
|
||
export DASHSCOPE_API_KEY="sk-xxx..."
|
||
|
||
# 方式2:使用 OpenAI
|
||
export OPENAI_API_KEY="sk-xxx..."
|
||
|
||
# 方式3:使用 DeepSeek(最便宜)
|
||
export DEEPSEEK_API_KEY="sk-xxx..."
|
||
```
|
||
|
||
#### 4. 修改前端 `mcpService.js`
|
||
|
||
```javascript
|
||
/**
|
||
* 智能对话 - 使用后端LLM处理
|
||
*/
|
||
async chat(userMessage, conversationHistory = []) {
|
||
try {
|
||
const response = await this.client.post('/chat', {
|
||
message: userMessage,
|
||
conversation_history: conversationHistory,
|
||
});
|
||
|
||
return {
|
||
success: true,
|
||
data: response,
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
error: error.message || '对话处理失败',
|
||
};
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 5. 修改前端 `ChatInterface.js`
|
||
|
||
```javascript
|
||
const handleSendMessage = async () => {
|
||
// ...
|
||
|
||
try {
|
||
// 调用后端聊天API
|
||
const response = await mcpService.chat(inputValue, messages);
|
||
|
||
if (response.success) {
|
||
const botMessage = {
|
||
id: Date.now() + 1,
|
||
content: response.data.message, // LLM总结的自然语言
|
||
isUser: false,
|
||
type: 'text',
|
||
timestamp: new Date().toISOString(),
|
||
toolUsed: response.data.tool_used, // 可选:显示使用了哪个工具
|
||
rawData: response.data.raw_data, // 可选:原始数据(折叠显示)
|
||
};
|
||
setMessages((prev) => [...prev, botMessage]);
|
||
}
|
||
} catch (error) {
|
||
// ...
|
||
}
|
||
};
|
||
```
|
||
|
||
## 💰 LLM 选择和成本
|
||
|
||
### 推荐:通义千问(阿里云)
|
||
|
||
**优点**:
|
||
- 价格便宜(1000次对话约 ¥1-2)
|
||
- 中文理解能力强
|
||
- 国内访问稳定
|
||
|
||
**价格**:
|
||
- qwen-plus: ¥0.004/1000 tokens(约 ¥0.001/次对话)
|
||
- qwen-turbo: ¥0.002/1000 tokens(更便宜)
|
||
|
||
**获取 API Key**:
|
||
1. 访问 https://dashscope.console.aliyun.com/
|
||
2. 创建 API Key
|
||
3. 设置环境变量 `DASHSCOPE_API_KEY`
|
||
|
||
### 其他选择
|
||
|
||
| 提供商 | 模型 | 价格 | 优点 | 缺点 |
|
||
|--------|------|------|------|------|
|
||
| **通义千问** | qwen-plus | ¥0.001/次 | 便宜、中文好 | - |
|
||
| **DeepSeek** | deepseek-chat | ¥0.0005/次 | 最便宜 | 新公司 |
|
||
| **OpenAI** | gpt-4o-mini | $0.15/1M tokens | 能力强 | 贵、需翻墙 |
|
||
| **Claude** | claude-3-haiku | $0.25/1M tokens | 理解力强 | 贵、需翻墙 |
|
||
|
||
## 🚀 部署步骤
|
||
|
||
### 1. 后端部署
|
||
|
||
```bash
|
||
# 安装依赖
|
||
pip install openai
|
||
|
||
# 设置 API Key
|
||
export DASHSCOPE_API_KEY="sk-xxx..."
|
||
|
||
# 重启服务
|
||
sudo systemctl restart mcp-server
|
||
|
||
# 测试聊天端点
|
||
curl -X POST https://valuefrontier.cn/mcp/chat \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"message": "查询贵州茅台的股票信息"}'
|
||
```
|
||
|
||
### 2. 前端部署
|
||
|
||
```bash
|
||
# 构建
|
||
npm run build
|
||
|
||
# 部署
|
||
scp -r build/* user@server:/var/www/valuefrontier.cn/
|
||
```
|
||
|
||
### 3. 验证
|
||
|
||
访问 https://valuefrontier.cn/agent-chat,测试对话:
|
||
|
||
**测试用例**:
|
||
1. "查询贵州茅台的股票信息" → 应返回自然语言总结
|
||
2. "今日涨停的股票有哪些" → 应返回涨停股票列表并总结
|
||
3. "新能源概念板块表现如何" → 应搜索概念并分析
|
||
|
||
## 📊 对比总结
|
||
|
||
| 特性 | 简单匹配 | 前端LLM | 后端LLM ⭐ |
|
||
|------|---------|---------|-----------|
|
||
| 实现难度 | 简单 | 中等 | 中等 |
|
||
| 用户体验 | 差 | 好 | 好 |
|
||
| 安全性 | 高 | 低 | 高 |
|
||
| 成本 | 无 | 用户承担 | 服务器承担 |
|
||
| 可维护性 | 差 | 中 | 好 |
|
||
| **推荐指数** | ⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||
|
||
## 🎯 最终推荐
|
||
|
||
**生产环境:后端集成 LLM (方案 B)**
|
||
- 使用通义千问(qwen-plus)
|
||
- 成本低(约 ¥50/月,10000次对话)
|
||
- 安全可靠
|
||
|
||
**快速原型:前端集成 LLM (方案 A)**
|
||
- 适合演示
|
||
- 快速验证可行性
|
||
- 后续再迁移到后端
|