# API集成基础
## 🎯 学习目标
通过本章学习,您将能够:
- 理解AI API集成的基本原理和最佳实践
- 掌握GLM-4-Flash API的使用方法和特性
- 学会设计可靠的API调用和错误处理机制
- 在Chat-Room项目中实现智能AI助手功能
## 🤖 AI集成架构
### AI集成系统概览
```mermaid
graph TB
subgraph "AI集成架构"
A[用户消息
User Message] --> B[消息预处理
Message Preprocessing]
B --> C[AI触发检测
AI Trigger Detection]
C --> D[上下文管理
Context Management]
D --> E[API调用管理
API Call Manager]
E --> F[GLM-4-Flash API
GLM-4-Flash API]
F --> G[响应处理
Response Processing]
G --> H[后处理
Post Processing]
H --> I[消息发送
Message Sending]
J[配置管理
Config Manager] --> E
K[缓存系统
Cache System] --> E
L[限流控制
Rate Limiting] --> E
M[错误处理
Error Handling] --> E
end
subgraph "AI功能模块"
N[智能回复
Smart Reply]
O[内容总结
Content Summary]
P[语言翻译
Translation]
Q[情感分析
Sentiment Analysis]
end
G --> N
G --> O
G --> P
G --> Q
style A fill:#e8f5e8
style F fill:#f8d7da
style I fill:#fff3cd
```
### API调用流程
```mermaid
sequenceDiagram
participant U as 用户
participant C as Chat-Room客户端
participant S as Chat-Room服务器
participant AI as AI管理器
participant GLM as GLM-4-Flash API
participant DB as 数据库
Note over U,DB: AI助手调用流程
U->>C: 发送消息 "@AI 你好"
C->>S: 转发消息
S->>AI: 检测AI触发
AI->>AI: 解析用户意图
AI->>DB: 获取上下文历史
DB->>AI: 返回历史对话
AI->>AI: 构建API请求
AI->>GLM: 调用GLM-4-Flash API
alt API调用成功
GLM->>AI: 返回AI响应
AI->>AI: 处理响应内容
AI->>S: 返回处理结果
S->>C: 广播AI回复
C->>U: 显示AI回复
AI->>DB: 保存对话记录
else API调用失败
GLM->>AI: 返回错误信息
AI->>AI: 错误处理和重试
AI->>S: 返回错误提示
S->>C: 发送错误消息
end
```
## 🔌 API集成实现
### 智谱AI客户端实现
```python
# server/ai/zhipu_client.py - 智谱AI API客户端
import os
import time
from typing import Dict, List, Optional, Any
from dataclasses import dataclass
try:
from zhipuai import ZhipuAI
ZHIPU_SDK_AVAILABLE = True
except ImportError:
ZHIPU_SDK_AVAILABLE = False
print("⚠️ 智谱AI官方SDK未安装,将使用HTTP API方式")
print("💡 建议安装官方SDK: pip install zhipuai")
# 备用HTTP API实现
import json
import requests
@dataclass
class AIMessage:
"""AI消息数据类"""
role: str # "user", "assistant", "system"
content: str
timestamp: Optional[float] = None
class ZhipuClient:
"""智谱AI API客户端"""
def __init__(self, api_key: str = None):
"""
初始化智谱AI客户端
Args:
api_key: 智谱AI API密钥,如果为None则从配置文件获取
"""
if api_key:
self.api_key = api_key
else:
# 从配置文件获取API密钥
try:
from server.config.server_config import get_server_config
server_config = get_server_config()
self.api_key = server_config.get_ai_api_key()
except Exception:
# 备用方案:从环境变量获取
self.api_key = os.getenv('ZHIPU_API_KEY', '')
if not self.api_key:
raise ValueError("智谱AI API密钥未设置")
# 模型配置 - 使用GLM-4-Flash免费模型
self.model = "glm-4-flash" # 使用免费的GLM-4-Flash模型
self.max_tokens = 1024
self.temperature = 0.7
self.top_p = 0.9
# 初始化客户端
if ZHIPU_SDK_AVAILABLE:
self.client = ZhipuAI(api_key=self.api_key)
self.use_sdk = True
print("✅ 使用智谱AI官方SDK")
else:
# 备用HTTP API配置
self.base_url = "https://open.bigmodel.cn/api/paas/v4"
self.headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
self.use_sdk = False
print("⚠️ 使用HTTP API方式调用智谱AI")
def chat_completion(self, messages: List[AIMessage],
system_prompt: str = None) -> Optional[str]:
"""
调用智谱AI聊天完成API
Args:
messages: 对话消息列表
system_prompt: 系统提示词
Returns:
AI回复内容,失败时返回None
"""
try:
# 构建请求消息
api_messages = []
# 添加系统提示词
if system_prompt:
api_messages.append({
"role": "system",
"content": system_prompt
})
# 添加对话消息
for msg in messages:
api_messages.append({
"role": msg.role,
"content": msg.content
})
if self.use_sdk:
# 使用官方SDK调用
return self._chat_completion_sdk(api_messages)
else:
# 使用HTTP API调用
return self._chat_completion_http(api_messages)
except Exception as e:
print(f"智谱AI API调用错误: {e}")
return None
def _chat_completion_sdk(self, api_messages: List[Dict]) -> Optional[str]:
"""
使用官方SDK调用聊天完成API
Args:
api_messages: API消息列表
Returns:
AI回复内容
"""
try:
response = self.client.chat.completions.create(
model=self.model,
messages=api_messages,
max_tokens=self.max_tokens,
temperature=self.temperature,
top_p=self.top_p,
stream=False
)
if response.choices and len(response.choices) > 0:
return response.choices[0].message.content.strip()
else:
print("智谱AI SDK响应格式错误:没有choices")
return None
except Exception as e:
print(f"智谱AI SDK调用错误: {e}")
return None
def _chat_completion_http(self, api_messages: List[Dict]) -> Optional[str]:
"""
使用HTTP API调用聊天完成API
Args:
api_messages: API消息列表
Returns:
AI回复内容
"""
try:
# 构建请求数据
request_data = {
"model": self.model,
"messages": api_messages,
"max_tokens": self.max_tokens,
"temperature": self.temperature,
"top_p": self.top_p,
"stream": False
}
# 发送请求
response = requests.post(
f"{self.base_url}/chat/completions",
headers=self.headers,
json=request_data,
timeout=30
)
# 检查响应状态
if response.status_code != 200:
print(f"智谱AI API请求失败: {response.status_code} - {response.text}")
return None
# 解析响应
response_data = response.json()
if "choices" not in response_data or not response_data["choices"]:
print("智谱AI API响应格式错误")
return None
# 提取AI回复
ai_reply = response_data["choices"][0]["message"]["content"]
return ai_reply.strip()
except Exception as e:
print(f"智谱AI HTTP API调用错误: {e}")
return None
def simple_chat(self, user_message: str, system_prompt: str = None) -> Optional[str]:
"""
简单聊天接口
Args:
user_message: 用户消息
system_prompt: 系统提示词
Returns:
AI回复内容
"""
messages = [AIMessage(role="user", content=user_message, timestamp=time.time())]
return self.chat_completion(messages, system_prompt)
def test_connection(self) -> bool:
"""
测试API连接
Returns:
连接是否成功
"""
try:
response = self.simple_chat("你好", "你是一个友好的AI助手,请简短回复。")
return response is not None and len(response.strip()) > 0
except Exception as e:
print(f"智谱AI连接测试失败: {e}")
return False
def get_model_info(self) -> Dict[str, Any]:
"""
获取模型信息
Returns:
模型信息字典
"""
return {
"model": self.model,
"max_tokens": self.max_tokens,
"temperature": self.temperature,
"top_p": self.top_p,
"api_key_set": bool(self.api_key),
"use_sdk": self.use_sdk,
"sdk_available": ZHIPU_SDK_AVAILABLE
}
# 使用示例
def demo_zhipu_client():
"""智谱AI客户端演示"""
print("=== 智谱AI客户端演示 ===")
try:
# 初始化客户端
client = ZhipuClient()
# 测试连接
print("测试API连接...")
if client.test_connection():
print("✅ API连接成功")
else:
print("❌ API连接失败")
return
# 获取模型信息
model_info = client.get_model_info()
print(f"模型信息: {model_info}")
# 简单聊天
print("\n--- 简单聊天测试 ---")
response = client.simple_chat(
user_message="你好,请介绍一下你自己",
system_prompt="你是一个友好的AI助手,名叫小智。请简短回复。"
)
if response:
print(f"AI回复: {response}")
else:
print("❌ 聊天请求失败")
# 带上下文的对话
print("\n--- 上下文对话测试 ---")
messages = [
AIMessage(role="user", content="我叫张三"),
AIMessage(role="assistant", content="你好张三,很高兴认识你!"),
AIMessage(role="user", content="你还记得我的名字吗?")
]
response = client.chat_completion(
messages=messages,
system_prompt="你是一个有记忆的AI助手。"
)
if response:
print(f"AI回复(带上下文): {response}")
else:
print("❌ 上下文对话失败")
except Exception as e:
print(f"演示过程中出现错误: {e}")
if __name__ == "__main__":
demo_zhipu_client()
```
## 🔧 Chat-Room中的AI集成
### AI管理器实现
```python
# server/ai/ai_manager.py - AI管理器
import time
from typing import Dict, List, Optional, Any
from dataclasses import dataclass
from .zhipu_client import ZhipuClient, AIMessage
@dataclass
class ChatContext:
"""聊天上下文"""
user_id: int
group_id: Optional[int]
conversation_history: List[AIMessage]
last_interaction: float
def add_message(self, role: str, content: str):
"""添加消息到历史"""
self.conversation_history.append(
AIMessage(role=role, content=content, timestamp=time.time())
)
self.last_interaction = time.time()
# 限制历史长度
if len(self.conversation_history) > 20:
self.conversation_history = self.conversation_history[-20:]
class AIManager:
"""AI管理器 - 管理Chat-Room中的AI功能"""
def __init__(self, api_key: str = None):
"""
初始化AI管理器
Args:
api_key: 智谱AI API密钥
"""
self.zhipu_client = ZhipuClient(api_key)
self.contexts: Dict[str, ChatContext] = {} # 用户上下文缓存
self.enabled = True
# AI配置
self.system_prompt = """你是Chat-Room聊天室的AI助手,名叫小智。
你的特点:
1. 友好、有帮助、有趣
2. 回复简洁明了,通常不超过100字
3. 能够参与群聊讨论
4. 可以回答问题、提供建议
5. 保持积极正面的态度
请根据聊天内容自然地参与对话。"""
# 测试连接
if not self.zhipu_client.test_connection():
print("⚠️ 智谱AI连接失败,AI功能将被禁用")
self.enabled = False
else:
print("✅ 智谱AI连接成功,AI功能已启用")
def is_enabled(self) -> bool:
"""检查AI功能是否启用"""
return self.enabled
def should_respond(self, message_content: str) -> bool:
"""
判断是否应该响应消息
Args:
message_content: 消息内容
Returns:
是否应该响应
"""
if not self.enabled:
return False
# 检查是否包含@AI标记(不区分大小写)
message_lower = message_content.lower()
return "@ai" in message_lower or "@小智" in message_lower
def get_context_key(self, user_id: int, group_id: Optional[int]) -> str:
"""获取上下文键"""
if group_id:
return f"group_{group_id}_user_{user_id}"
else:
return f"private_user_{user_id}"
def get_or_create_context(self, user_id: int, group_id: Optional[int]) -> ChatContext:
"""获取或创建聊天上下文"""
context_key = self.get_context_key(user_id, group_id)
if context_key not in self.contexts:
self.contexts[context_key] = ChatContext(
user_id=user_id,
group_id=group_id,
conversation_history=[],
last_interaction=time.time()
)
return self.contexts[context_key]
def generate_response(self, user_message: str, user_id: int,
group_id: Optional[int] = None,
username: str = None) -> Optional[str]:
"""
生成AI响应
Args:
user_message: 用户消息
user_id: 用户ID
group_id: 群组ID(私聊时为None)
username: 用户名
Returns:
AI响应内容
"""
if not self.enabled:
return None
try:
# 获取上下文
context = self.get_or_create_context(user_id, group_id)
# 清理@AI标记
clean_message = user_message.replace("@AI", "").replace("@ai", "").replace("@小智", "").strip()
# 构建消息历史
messages = context.conversation_history.copy()
# 添加用户名信息到消息中
if username:
user_message_with_name = f"{username}: {clean_message}"
else:
user_message_with_name = clean_message
messages.append(AIMessage(
role="user",
content=user_message_with_name,
timestamp=time.time()
))
# 调用AI API
ai_response = self.zhipu_client.chat_completion(
messages=messages,
system_prompt=self.system_prompt
)
if ai_response:
# 更新上下文
context.add_message("user", user_message_with_name)
context.add_message("assistant", ai_response)
return ai_response
else:
return "抱歉,我现在无法回复,请稍后再试。"
except Exception as e:
print(f"AI响应生成错误: {e}")
return "抱歉,我遇到了一些技术问题。"
def clear_context(self, user_id: int, group_id: Optional[int] = None):
"""清除用户上下文"""
context_key = self.get_context_key(user_id, group_id)
if context_key in self.contexts:
del self.contexts[context_key]
def cleanup_old_contexts(self, max_age_hours: int = 24):
"""清理过期的上下文"""
current_time = time.time()
max_age_seconds = max_age_hours * 3600
expired_keys = []
for key, context in self.contexts.items():
if current_time - context.last_interaction > max_age_seconds:
expired_keys.append(key)
for key in expired_keys:
del self.contexts[key]
if expired_keys:
print(f"清理了 {len(expired_keys)} 个过期的AI上下文")
def get_stats(self) -> Dict[str, Any]:
"""获取AI管理器统计信息"""
return {
"enabled": self.enabled,
"active_contexts": len(self.contexts),
"model_info": self.zhipu_client.get_model_info() if self.enabled else None
}
# 使用示例
def demo_ai_manager():
"""AI管理器演示"""
print("=== AI管理器演示 ===")
# 初始化AI管理器
ai_manager = AIManager()
if not ai_manager.is_enabled():
print("AI功能未启用,跳过演示")
return
# 模拟群聊场景
print("\n--- 群聊AI响应测试 ---")
# 用户1发送消息
message1 = "@AI 你好,请介绍一下自己"
if ai_manager.should_respond(message1):
response1 = ai_manager.generate_response(
user_message=message1,
user_id=1,
group_id=1,
username="张三"
)
print(f"用户: {message1}")
print(f"AI: {response1}")
# 用户2发送消息
message2 = "@AI 你能帮我解答编程问题吗?"
if ai_manager.should_respond(message2):
response2 = ai_manager.generate_response(
user_message=message2,
user_id=2,
group_id=1,
username="李四"
)
print(f"用户: {message2}")
print(f"AI: {response2}")
# 查看统计信息
stats = ai_manager.get_stats()
print(f"\nAI管理器统计: {stats}")
if __name__ == "__main__":
demo_ai_manager()
```
## 🎯 实践练习
### 练习1:API配置管理
```python
class APIConfigManager:
"""
API配置管理练习
要求:
1. 支持从配置文件加载API密钥
2. 实现配置验证机制
3. 支持环境变量覆盖
4. 添加配置热更新功能
"""
def load_config_from_file(self, config_path: str) -> Dict[str, Any]:
"""从文件加载配置"""
# TODO: 实现配置文件加载
pass
def validate_config(self, config: Dict[str, Any]) -> bool:
"""验证配置有效性"""
# TODO: 实现配置验证
pass
def get_api_key(self) -> str:
"""获取API密钥"""
# TODO: 实现API密钥获取逻辑
pass
```
### 练习2:AI响应缓存
```python
class AIResponseCache:
"""
AI响应缓存练习
要求:
1. 实现基于消息内容的缓存
2. 支持TTL过期机制
3. 添加缓存命中率统计
4. 实现缓存清理策略
"""
def get_cached_response(self, message_hash: str) -> Optional[str]:
"""获取缓存响应"""
# TODO: 实现缓存查询
pass
def cache_response(self, message_hash: str, response: str, ttl: int = 3600):
"""缓存响应"""
# TODO: 实现响应缓存
pass
def get_cache_stats(self) -> Dict[str, Any]:
"""获取缓存统计"""
# TODO: 实现缓存统计
pass
## ✅ 学习检查
完成本章学习后,请确认您能够:
- [ ] 理解智谱AI API集成的基本架构
- [ ] 配置和使用GLM-4-Flash免费模型
- [ ] 实现同步API调用和错误处理
- [ ] 设计AI管理器管理聊天上下文
- [ ] 在Chat-Room中集成AI功能
- [ ] 完成实践练习
## 📚 下一步
API集成基础掌握后,请继续学习:
- [GLM-4-Flash特性](glm-4-flash-features.md)
- [上下文管理](context-management.md)
- [AI响应优化](ai-response-optimization.md)
---
**现在您已经掌握了智谱AI API集成的核心技术!** 🤖
def _build_request(self, messages: List[ChatMessage], stream: bool) -> Dict[str, Any]:
"""构建API请求"""
return {
"model": self.config.model,
"messages": [msg.to_dict() for msg in messages],
"max_tokens": self.config.max_tokens,
"temperature": self.config.temperature,
"top_p": self.config.top_p,
"stream": stream
}
async def _make_request(self, request_data: Dict[str, Any],
stream: bool) -> APIResponse:
"""执行API请求"""
headers = {
"Authorization": f"Bearer {self.config.api_key}",
"Content-Type": "application/json"
}
url = f"{self.config.base_url}/chat/completions"
for attempt in range(self.config.max_retries):
try:
async with self.session.post(url, json=request_data, headers=headers) as response:
if response.status == 200:
if stream:
return await self._handle_stream_response(response)
else:
return await self._handle_normal_response(response)
else:
error_text = await response.text()
self.logger.warning(f"API请求失败 (状态码: {response.status}): {error_text}")
if attempt < self.config.max_retries - 1:
await asyncio.sleep(self.config.retry_delay * (2 ** attempt))
continue
return APIResponse(
success=False,
error_message=f"HTTP {response.status}: {error_text}",
error_code=str(response.status)
)
except asyncio.TimeoutError:
self.logger.warning(f"API请求超时 (尝试 {attempt + 1}/{self.config.max_retries})")
if attempt < self.config.max_retries - 1:
await asyncio.sleep(self.config.retry_delay * (2 ** attempt))
continue
return APIResponse(
success=False,
error_message="请求超时",
error_code="TIMEOUT"
)
except Exception as e:
self.logger.error(f"API请求异常 (尝试 {attempt + 1}/{self.config.max_retries}): {e}")
if attempt < self.config.max_retries - 1:
await asyncio.sleep(self.config.retry_delay * (2 ** attempt))
continue
return APIResponse(
success=False,
error_message=str(e),
error_code="REQUEST_ERROR"
)
return APIResponse(
success=False,
error_message="所有重试尝试都失败了",
error_code="MAX_RETRIES_EXCEEDED"
)
async def _handle_normal_response(self, response: aiohttp.ClientResponse) -> APIResponse:
"""处理普通响应"""
try:
data = await response.json()
if "choices" in data and len(data["choices"]) > 0:
content = data["choices"][0]["message"]["content"]
usage = data.get("usage", {})
return APIResponse(
success=True,
content=content,
usage=usage
)
else:
return APIResponse(
success=False,
error_message="响应格式错误:缺少choices字段",
error_code="INVALID_RESPONSE"
)
except json.JSONDecodeError as e:
return APIResponse(
success=False,
error_message=f"JSON解析错误: {e}",
error_code="JSON_DECODE_ERROR"
)
async def _handle_stream_response(self, response: aiohttp.ClientResponse) -> APIResponse:
"""处理流式响应"""
content_parts = []
try:
async for line in response.content:
line = line.decode('utf-8').strip()
if line.startswith('data: '):
data_str = line[6:] # 移除 'data: ' 前缀
if data_str == '[DONE]':
break
try:
data = json.loads(data_str)
if "choices" in data and len(data["choices"]) > 0:
delta = data["choices"][0].get("delta", {})
if "content" in delta:
content_parts.append(delta["content"])
except json.JSONDecodeError:
continue
full_content = ''.join(content_parts)
return APIResponse(
success=True,
content=full_content
)
except Exception as e:
return APIResponse(
success=False,
error_message=f"流式响应处理错误: {e}",
error_code="STREAM_ERROR"
)
async def _wait_for_rate_limit(self):
"""等待限流"""
current_time = time.time()
time_since_last = current_time - self.last_request_time
if time_since_last < self.min_request_interval:
await asyncio.sleep(self.min_request_interval - time_since_last)
self.last_request_time = time.time()
def _update_stats(self, response: APIResponse):
"""更新统计信息"""
self.stats['total_requests'] += 1
if response.success:
self.stats['successful_requests'] += 1
if response.usage:
self.stats['total_tokens_used'] += response.usage.get('total_tokens', 0)
else:
self.stats['failed_requests'] += 1
if response.response_time:
self.stats['total_response_time'] += response.response_time
def get_stats(self) -> Dict[str, Any]:
"""获取统计信息"""
stats = self.stats.copy()
if stats['total_requests'] > 0:
stats['success_rate'] = stats['successful_requests'] / stats['total_requests']
stats['average_response_time'] = stats['total_response_time'] / stats['total_requests']
else:
stats['success_rate'] = 0.0
stats['average_response_time'] = 0.0
return stats
# 使用示例
async def demo_glm_client():
"""GLM客户端演示"""
# 配置(实际使用时需要真实的API密钥)
config = GLMConfig(
api_key="your_api_key_here",
model="glm-4-flash",
max_tokens=512,
temperature=0.7
)
print("=== GLM-4-Flash API客户端演示 ===")
async with GLMClient(config) as client:
# 简单聊天
response = await client.simple_chat(
user_message="你好,请介绍一下你自己",
system_prompt="你是一个友好的AI助手,名叫小智。"
)
if response.success:
print(f"AI回复: {response.content}")
print(f"响应时间: {response.response_time:.2f}秒")
if response.usage:
print(f"Token使用: {response.usage}")
else:
print(f"请求失败: {response.error_message}")
# 带上下文的对话
history = [
ChatMessage(MessageRole.USER, "我叫张三"),
ChatMessage(MessageRole.ASSISTANT, "你好张三,很高兴认识你!")
]
response = await client.chat_with_context(
user_message="你还记得我的名字吗?",
conversation_history=history,
system_prompt="你是一个有记忆的AI助手。"
)
if response.success:
print(f"AI回复(带上下文): {response.content}")
# 查看统计信息
stats = client.get_stats()
print(f"API调用统计: {stats}")
if __name__ == "__main__":
asyncio.run(demo_glm_client())
```
## 🎯 实践练习
### 练习1:API配置管理
```python
class APIConfigManager:
"""
API配置管理练习
要求:
1. 支持多个API提供商配置
2. 实现配置热更新
3. 添加配置验证机制
4. 支持环境变量覆盖
"""
def load_config_from_file(self, config_path: str) -> GLMConfig:
"""从文件加载配置"""
# TODO: 实现配置文件加载
pass
def validate_config(self, config: GLMConfig) -> bool:
"""验证配置有效性"""
# TODO: 实现配置验证
pass
```
### 练习2:API响应缓存
```python
class APIResponseCache:
"""
API响应缓存练习
要求:
1. 实现基于内容哈希的缓存
2. 支持TTL过期机制
3. 添加缓存命中率统计
4. 实现缓存清理策略
"""
def get_cached_response(self, request_hash: str) -> Optional[APIResponse]:
"""获取缓存响应"""
# TODO: 实现缓存查询
pass
def cache_response(self, request_hash: str, response: APIResponse):
"""缓存响应"""
# TODO: 实现响应缓存
pass
```
## ✅ 学习检查
完成本章学习后,请确认您能够:
- [ ] 理解AI API集成的基本架构
- [ ] 配置和使用GLM-4-Flash API
- [ ] 实现异步API调用和错误处理
- [ ] 设计限流和重试机制
- [ ] 管理API调用统计和监控
- [ ] 完成实践练习
## 📚 下一步
API集成基础掌握后,请继续学习:
- [GLM-4-Flash特性](glm-4-flash-features.md)
- [上下文管理](context-management.md)
- [异步处理](async-processing.md)
---
**现在您已经掌握了AI API集成的核心技术!** 🤖