feat: 实现 AI-First 代理系统
核心功能: - AIAgent 模型:AI 代理身份管理 - AIOperationLog: AI 操作日志记录 - AITask: AI 异步任务系统 - AIWebhook: AI webhook 订阅 API 端点: - POST /api/agents/auth/ - AI 代理认证 - GET/POST /api/agents/ - 代理管理 - GET /api/agent-logs/ - 操作日志查询 - GET/POST /api/agent-tasks/ - 任务管理 - GET/POST /api/agent-webhooks/ - Webhook 管理 - POST /api/batch/ - 批量操作 预置 AI 代理: - content-moderator-ai: 内容审核 AI - content-generator-ai: 内容生成 AI - service-curator-ai: 服务推荐 AI - analytics-ai: 数据分析 AI - admin-ai: 管理员 AI 文档: - AI_AGENT.md: AI-First 设计文档 - init_agents.py: AI 代理初始化脚本 测试: - 认证系统测试通过 - JWT token 生成正常 - 权限系统工作正常
This commit is contained in:
131
city-manual/backend/agents/serializers.py
Normal file
131
city-manual/backend/agents/serializers.py
Normal file
@@ -0,0 +1,131 @@
|
||||
from rest_framework import serializers
|
||||
from .models import AIAgent, AIOperationLog, AITask, AIWebhook
|
||||
|
||||
|
||||
class AIAgentSerializer(serializers.ModelSerializer):
|
||||
"""AI 代理序列化器"""
|
||||
|
||||
permissions = serializers.ListField(
|
||||
child=serializers.CharField(),
|
||||
required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = AIAgent
|
||||
fields = [
|
||||
'id', 'agent_id', 'name', 'description', 'permissions',
|
||||
'rate_limit', 'rate_limit_window', 'is_active', 'last_seen',
|
||||
'created_at', 'updated_at'
|
||||
]
|
||||
read_only_fields = ['id', 'created_at', 'updated_at', 'last_seen']
|
||||
extra_kwargs = {
|
||||
'secret_key': {'write_only': True}
|
||||
}
|
||||
|
||||
|
||||
class AIAgentAuthSerializer(serializers.Serializer):
|
||||
"""AI 代理认证序列化器"""
|
||||
|
||||
agent_id = serializers.CharField()
|
||||
agent_secret = serializers.CharField()
|
||||
|
||||
def validate(self, data):
|
||||
try:
|
||||
agent = AIAgent.objects.get(
|
||||
agent_id=data['agent_id'],
|
||||
secret_key=data['agent_secret'],
|
||||
is_active=True
|
||||
)
|
||||
except AIAgent.DoesNotExist:
|
||||
raise serializers.ValidationError("Invalid agent credentials")
|
||||
|
||||
# 更新最后活跃时间
|
||||
from django.utils import timezone
|
||||
agent.last_seen = timezone.now()
|
||||
agent.save()
|
||||
|
||||
self.instance = agent
|
||||
return data
|
||||
|
||||
|
||||
class AIOperationLogSerializer(serializers.ModelSerializer):
|
||||
"""AI 操作日志序列化器"""
|
||||
|
||||
agent_id = serializers.CharField(source='agent.agent_id', read_only=True)
|
||||
agent_name = serializers.CharField(source='agent.name', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = AIOperationLog
|
||||
fields = [
|
||||
'id', 'agent_id', 'agent_name', 'action', 'resource_type',
|
||||
'resource_id', 'status', 'confidence', 'reasoning',
|
||||
'execution_time_ms', 'created_at'
|
||||
]
|
||||
read_only_fields = ['id', 'created_at']
|
||||
|
||||
|
||||
class AITaskSerializer(serializers.ModelSerializer):
|
||||
"""AI 任务序列化器"""
|
||||
|
||||
agent_id = serializers.CharField(source='agent.agent_id', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = AITask
|
||||
fields = [
|
||||
'id', 'task_id', 'agent_id', 'task_type', 'status',
|
||||
'progress', 'processed_items', 'total_items', 'result',
|
||||
'error_message', 'callback_url', 'created_at', 'started_at', 'completed_at'
|
||||
]
|
||||
read_only_fields = ['id', 'created_at', 'started_at', 'completed_at']
|
||||
|
||||
|
||||
class AITaskCreateSerializer(serializers.Serializer):
|
||||
"""AI 任务创建序列化器"""
|
||||
|
||||
task_type = serializers.CharField()
|
||||
operations = serializers.ListField(required=False)
|
||||
callback_url = serializers.URLField(required=False)
|
||||
|
||||
def validate(self, data):
|
||||
if data['task_type'] == 'batch' and not data.get('operations'):
|
||||
raise serializers.ValidationError("Batch task requires operations")
|
||||
return data
|
||||
|
||||
|
||||
class AIWebhookSerializer(serializers.ModelSerializer):
|
||||
"""AI Webhook 序列化器"""
|
||||
|
||||
agent_id = serializers.CharField(source='agent.agent_id', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = AIWebhook
|
||||
fields = [
|
||||
'id', 'agent_id', 'event', 'url', 'is_active',
|
||||
'last_triggered', 'failure_count', 'created_at'
|
||||
]
|
||||
read_only_fields = ['id', 'created_at', 'last_triggered', 'failure_count']
|
||||
extra_kwargs = {
|
||||
'secret': {'write_only': True}
|
||||
}
|
||||
|
||||
|
||||
class BatchOperationSerializer(serializers.Serializer):
|
||||
"""批量操作序列化器"""
|
||||
|
||||
operations = serializers.ListField(
|
||||
child=serializers.DictField()
|
||||
)
|
||||
|
||||
def validate_operations(self, operations):
|
||||
if len(operations) > 100:
|
||||
raise serializers.ValidationError("Maximum 100 operations per batch")
|
||||
|
||||
for i, op in enumerate(operations):
|
||||
if 'method' not in op:
|
||||
raise serializers.ValidationError(f"Operation {i}: missing 'method'")
|
||||
if op['method'] not in ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']:
|
||||
raise serializers.ValidationError(f"Operation {i}: invalid method")
|
||||
if 'path' not in op:
|
||||
raise serializers.ValidationError(f"Operation {i}: missing 'path'")
|
||||
|
||||
return operations
|
||||
Reference in New Issue
Block a user