4.3 应用框架集成 — AI知识库搭建全攻略 本节导读:深入掌握AI知识库与主流应用框架的集成技术,包括Web框架、移动端框架、API框架等,实现知识库与各类应用的无缝对接。 学习目标 掌握AI知识库与Web框架的集成方法 学会与移动端应用框架的集成技术 了解API网关和微服务集成方案 能够实现完整的端到端集成架构 掌握集成测试和部署的最佳实践 集成架构概述 AI知识库的集成架构需要考虑不同类型应用的接入需求,实现统一的数据访问和业务逻辑: Web框架集成 Flask集成方案 Flask作为轻量级Web框架,与AI知识库集成简单高效: Django集成方案 Django作为全栈Web框架,提供了更完整的集成方案: 移动端集成 React Native集成 API网关集成 Kong网关配置
本节导读:深入掌握AI知识库与主流应用框架的集成技术,包括Web框架、移动端框架、API框架等,实现知识库与各类应用的无缝对接。
AI知识库的集成架构需要考虑不同类型应用的接入需求,实现统一的数据访问和业务逻辑:
Flask作为轻量级Web框架,与AI知识库集成简单高效:
from flask import Flask, request, jsonify from knowledge_base import KnowledgeBase from auth_manager import AuthManager from rate_limiter import RateLimiter app = Flask(__name__) kb = KnowledgeBase() auth = AuthManager() rate_limiter = RateLimiter() @app.route('/api/search', methods=['POST']) def search(): """搜索接口""" # 身份验证 user_id = auth.authenticate_request(request) if not user_id: return jsonify({'error': 'Authentication failed'}), 401 # 限流检查 if not rate_limiter.check_rate_limit(user_id): return jsonify({'error': 'Rate limit exceeded'}), 429 # 获取查询参数 query = request.json.get('query', '') top_k = request.json.get('top_k', 10) # 执行搜索 results = kb.search(query, top_k=top_k) # 返回结果 return jsonify({ 'results': results, 'total': len(results), 'query': query }) @app.route('/api/document/<doc_id>', methods=['GET']) def get_document(doc_id): """获取文档""" user_id = auth.authenticate_request(request) if not user_id: return jsonify({'error': 'Authentication failed'}), 401 document = kb.get_document(doc_id) if not document: return jsonify({'error': 'Document not found'}), 404 return jsonify(document) if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=5000)
Django作为全栈Web框架,提供了更完整的集成方案:
# settings.py INSTALLED_APPS = [ ... 'rest_framework', 'corsheaders', 'knowledge_base', ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ], 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 20 } CORS_ALLOW_ALL_ORIGINS = True # 生产环境应配置具体的域名
# views.py from rest_framework import viewsets, permissions, status from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from knowledge_base.models import Document, SearchResult from knowledge_base.services import SearchService, DocumentService class DocumentViewSet(viewsets.ModelViewSet): """文档视图集""" permission_classes = [IsAuthenticated] queryset = Document.objects.all() serializer_class = DocumentSerializer def get_queryset(self): """根据权限过滤文档""" user = self.request.user if user.is_superuser: return Document.objects.all() return Document.objects.filter(visible_to_users__in=[user]) @action(detail=False, methods=['post']) def search(self, request): """搜索文档""" query = request.data.get('query', '') top_k = int(request.data.get('top_k', 10)) filters = request.data.get('filters', {}) search_service = SearchService() results = search_service.search(query, top_k=top_k, filters=filters) return Response({ 'results': results, 'total': len(results), 'query': query })
import React, { useState, useEffect } from 'react'; import { View, Text, TextInput, Button, FlatList, ActivityIndicator, StyleSheet } from 'react-native'; const KnowledgeBaseScreen = () => { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const searchKnowledgeBase = async () => { if (!query.trim()) return; setLoading(true); setError(null); try { const response = await fetch('https://your-api.com/api/search', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${await getAuthToken()}`, }, body: JSON.stringify({ query: query, top_k: 10, }), }); if (!response.ok) { throw new Error('Search failed'); } const data = await response.json(); setResults(data.results); } catch (err) { setError(err.message); } finally { setLoading(false); } }; return ( <View style={styles.container}> <TextInput style={styles.input} placeholder="输入搜索内容..." value={query} onChangeText={setQuery} /> <Button title="搜索" onPress={searchKnowledgeBase} disabled={loading} /> {loading && <ActivityIndicator size="large" />} {error && <Text style={styles.error}>{error}</Text>} <FlatList data={results} keyExtractor={(item) => item.id} renderItem={({ item }) => ( <View style={styles.resultItem}> <Text style={styles.resultTitle}>{item.title}</Text> <Text style={styles.resultContent}>{item.content}</Text> <Text style={styles.resultScore}>相关度: {item.score}</Text> </View> )} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 16, }, input: { height: 40, borderColor: 'gray', borderWidth: 1, marginBottom: 16, paddingHorizontal: 8, }, error: { color: 'red', marginBottom: 16, }, resultItem: { padding: 16, borderBottomWidth: 1, borderBottomColor: '#eee', }, resultTitle: { fontSize: 16, fontWeight: 'bold', marginBottom: 8, }, resultContent: { fontSize: 14, color: '#666', marginBottom: 8, }, resultScore: { fontSize: 12, color: '#999', }, }); export default KnowledgeBaseScreen;
# kong.yml format_version: "2.0" services: - name: knowledge-base-api url: http://knowledge-base:8080 routes: - name: knowledge-base-route paths: ["/api/v1/*"] strip_path: true plugins: - name: cors config: origins: - "*" methods: - GET - POST - PUT - DELETE - OPTIONS headers: - Accept - Accept-Language - Content-Type - name: rate-limiting config: minute: 100 hour: 1000 - name: authentication config: anonymous: "off" key_names: ["Authorization"] header_names: ["X-API-Key"]
server { listen 80; server_name api.yourdomain.com; # 访问控制 allow 192.168.1.0/24; deny all; # 限流 limit_req_zone $binary_remote_addr zone=api:10m rate=100r/m; location / { limit_req zone=api burst=20 nodelay; proxy_pass http://knowledge-base:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 超时设置 proxy_connect_timeout 30s; proxy_read_timeout 30s; proxy_send_timeout 30s; } }
# service_registry.py from service_discovery import ServiceRegistry from consul import Consul class KnowledgeBaseRegistry: def __init__(self): self.consul = Consul() self.registry = ServiceRegistry() def register_service(self, service_name, service_id, address, port): """注册服务""" self.consul.agent.service.register( name=service_name, service_id=service_id, address=address, port=port, tags=["knowledge-base", "ai"], check=consul.Check.http( f"http://{address}:{port}/health", interval="10s", timeout="5s" ) ) def discover_service(self, service_name): """发现服务""" services = self.consul.health.service(service_name, passing=True) return services[0]['Service']['Address'], services[0]['Service']['Port']
# service_communication.py import requests import circuitbreaker from retry import retry class ServiceCommunicator: def __init__(self): self.base_urls = { 'user-service': 'http://user-service:8080', 'document-service': 'http://document-service:8080', 'search-service': 'http://search-service:8080', } @circuitbreaker.circuit(failure_threshold=5, recovery_timeout=30) @retry(tries=3, delay=1) def call_service(self, service_name, endpoint, method='GET', data=None): """调用微服务""" url = f"{self.base_urls[service_name]}{endpoint}" if method == 'GET': response = requests.get(url) elif method == 'POST': response = requests.post(url, json=data) elif method == 'PUT': response = requests.put(url, json=data) elif method == 'DELETE': response = requests.delete(url) response.raise_for_status() return response.json() def get_user_info(self, user_id): """获取用户信息""" return self.call_service('user-service', f'/users/{user_id}') def get_document(self, document_id): """获取文档信息""" return self.call_service('document-service', f'/documents/{document_id}')
# websocket_server.py import asyncio import websockets from knowledge_base import KnowledgeBase class KnowledgeBaseWebSocket: def __init__(self): self.kb = KnowledgeBase() self.clients = set() async def register_client(self, websocket): """注册客户端""" self.clients.add(websocket) await self.send_to_client(websocket, { 'type': 'connection_established', 'message': '连接已建立' }) async def handle_search(self, query): """处理搜索请求""" # 执行异步搜索 loop = asyncio.get_event_loop() results = await loop.run_in_executor( None, self.kb.search, query, 10 ) return results async def websocket_server(): kb_ws = KnowledgeBaseWebSocket() async def handler(websocket, path): await kb_ws.register_client(websocket) try: async for message in websocket: data = eval(message) if data['type'] == 'search': results = await kb_ws.handle_search(data['query']) await kb_ws.send_to_client(websocket, { 'type': 'search_results', 'results': results, 'query': data['query'] }) finally: await kb_ws.unregister_client(websocket) server = await websockets.serve(handler, "localhost", 8765) await server.wait_closed()
# test_integration.py import pytest from unittest.mock import Mock, patch from knowledge_base_integration import KnowledgeBaseIntegration class TestKnowledgeBaseIntegration: def setup_method(self): """测试前置设置""" self.integration = KnowledgeBaseIntegration() @patch('knowledge_base_integration.KnowledgeBase') def test_search_with_auth(self, mock_kb_class): """测试带认证的搜索""" # 设置模拟 mock_kb = Mock() mock_kb.search.return_value = [ {'id': '1', 'title': '文档1', 'content': '内容1', 'score': 0.95}, {'id': '2', 'title': '文档2', 'content': '内容2', 'score': 0.85} ] mock_kb_class.return_value = mock_kb mock_auth = Mock() mock_auth.authenticate.return_value = 'user123' self.integration.auth_service = mock_auth # 执行测试 result = self.integration.search_with_auth('test query', 'user_token') # 验证结果 assert len(result) == 2 assert result[0]['title'] == '文档1'
# Dockerfile FROM python:3.9-slim WORKDIR /app # 安装系统依赖 RUN apt-get update && apt-get install -y \ gcc \ g++ \ && rm -rf /var/lib/apt/lists/* # 安装Python依赖 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码 COPY . . # 设置环境变量 ENV PYTHONPATH=/app ENV FLASK_ENV=production # 暴露端口 EXPOSE 5000 # 健康检查 HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:5000/health || exit 1 # 启动命令 CMD ["python", "app.py"]
# k8s-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: knowledge-base-api labels: app: knowledge-base spec: replicas: 3 selector: matchLabels: app: knowledge-base template: metadata: labels: app: knowledge-base spec: containers: - name: knowledge-base image: your-registry/knowledge-base:latest ports: - containerPort: 5000 env: - name: DATABASE_URL valueFrom: secretKeyRef: name: db-secret key: url resources: requests: memory: "512Mi" cpu: "500m" limits: memory: "1Gi" cpu: "1000m" livenessProbe: httpGet: path: /health port: 5000 initialDelaySeconds: 30 periodSeconds: 10
# monitoring.py import prometheus_client from prometheus_client import Counter, Histogram, Gauge import time # 定义监控指标 REQUEST_COUNT = Counter( 'knowledge_base_requests_total', 'Total number of requests', ['method', 'endpoint', 'status'] ) REQUEST_DURATION = Histogram( 'knowledge_base_request_duration_seconds', 'Request duration in seconds', ['method', 'endpoint'] ) ACTIVE_CONNECTIONS = Gauge( 'knowledge_base_active_connections', 'Number of active connections' ) class MetricsCollector: def __init__(self): self.logger = logging.getLogger(__name__) def record_request(self, method, endpoint, duration, status): """记录请求指标""" REQUEST_COUNT.labels(method, endpoint, status).inc() REQUEST_DURATION.labels(method, endpoint).observe(duration) self.logger.info(f"Request: {method} {endpoint} - {status} - {duration:.3f}s")
本节深入探讨了AI知识库与各类应用框架的集成技术,涵盖了Web框架、移动端、API网关、微服务等集成方案:
Web框架集成:提供了Flask和Django的完整集成方案,包括认证、限流、错误处理等功能。
移动端集成:展示了React Native和Flutter的集成实现,实现了移动应用的知识库搜索功能。
API网关集成:配置了Kong和Nginx网关,实现了路由、限流、认证等网关功能。
微服务集成:实现了服务注册发现和服务间通信,支持高可用和容错机制。
实时集成:通过WebSocket实现了实时搜索功能,提供更好的用户体验。
集成测试:建立了完整的测试体系,包括单元测试和性能测试。
部署运维:提供了Docker容器化和Kubernetes部署方案,确保系统的可扩展性和可靠性。
监控日志:实现了应用监控和日志系统,支持Prometheus指标收集和结构化日志记录。
通过本节的学习,读者应该能够将AI知识库与各类应用无缝集成,构建完整的知识库应用生态。
关键词:AI知识库搭建全攻略, 应用框架集成, Web框架, 移动端集成, API网关, 微服务, WebSocket, Docker
难度:进阶
预计阅读:40分钟