BettaFish源码解析(七):工程实践与部署
从零开始构建生产级AI系统
前言

在前六篇文章中,我们分别讲解了BettaFish的整体架构、Agent论坛机制、GraphRAG知识图谱、报告生成引擎、分布式爬虫系统和情感分析模型层。这些都是系统的”功能组件”。
最后一篇,我们将站在”工程实践”的角度,讲解如何将这些组件组装成生产级AI系统,包括部署、监控、优化、安全等。
本文将深入解析BettaFish的工程实践,回答一个核心问题:
如何从零开始构建一个生产级的多Agent AI系统,包括部署、监控、优化、安全?
一、Docker多服务部署方案
1.1 Docker Compose架构
# docker-compose.ymlversion: "3.9"services: bettafish: image: ghcr.io/666ghj/bettafish:latest container_name: bettafish restart: unless-stopped environment: - PYTHONUNBUFFERED=1 - STREAMLIT_SERVER_ENABLE_FILE_WATCHER=false ports: - "5000:5000" - "8501:8501" - "8502:8502" - "8503:8503" volumes: - ./logs:/app/logs - ./final_reports:/app/final_reports - ./.env:/app/.env - ./insight_engine_streamlit_reports:/app/insight_engine_streamlit_reports - ./media_engine_streamlit_reports:/app/media_engine_streamlit_reports - ./query_engine_streamlit_reports:/app/query_engine_streamlit_reports db: image: postgres:15 container_name: bettafish-db restart: unless-stopped env_file: - .env environment: POSTGRES_USER: ${POSTGRES_USER:-bettafish} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-bettafish} POSTGRES_DB: ${POSTGRES_DB:-bettafish} ports: - "${POSTGRES_PORT:-5432}:5432" volumes: - ./db_data:/var/lib/postgresql/data
设计亮点:
-
服务分离:应用(BettaFish)和数据库(PostgreSQL)独立部署
-
持久化存储:
db_data、logs、final_reports通过volume持久化 -
环境变量注入:通过
.env文件统一管理配置 -
多端口暴露:5000(Flask主应用)+ 8501-8503(Streamlit子应用)
-
重启策略:
unless-stopped确保服务意外停止后自动重启
1.2 Dockerfile多阶段构建
# DockerfileFROM python:3.11-slimSHELL ["/bin/bash", "-o", "pipefail", "-c"]# 防止Python写入.pyc文件,缓冲stdout/stderr,固定常用工具路径ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PIP_NO_CACHE_DIR=1 \ PATH="/root/.local/bin:${PATH}" \ PLAYWRIGHT_BROWSERS_PATH=/ms-playwright# 安装科学Python栈、Playwright、Streamlit和WeasyPrint PDF生成所需的系统依赖RUN set -euo pipefail; \ apt-get update; \ if apt-cache show libgdk-pixbuf-2.0-0 >/dev/null 2>&1; then \ GDK_PIXBUF_PKG=libgdk-pixbuf-2.0-0; \ else \ GDK_PIXBUF_PKG=libgdk-pixbuf2.0.0; \ fi; \ apt-get install -y --no-install-recommends \ build-essential \ curl \ git \ libgl1 \ libglib2.0-0 \ libgtk-3-0 \ libpango-1.0-0 \ libpangocairo-1.0-0 \ libatk1.0-0 \ libatk-bridge2.0-0 \ libxcb1 \ libxcomposite1 \ libxdamage1 \ libxext6 \ libxfixes3 \ libxi6 \ libxrandr2 \ libxrender1 \ libxss \ libxtst6 \ libnss3 \ libxkbcommon0 \ libasound2 \ ffmpeg; \ apt-get clean; \ rm -rf /var/lib/apt/lists/*# 安装最新uv版本并暴露到PATHRUN curl -LsSf --retry 3 --retry-delay 2 --proto '=https' --proto-redir '=https' --tlsv1.2 https://astral.sh/uv/install.sh | shWORKDIR /app# 利用Docker层缓存优先安装Python依赖COPY requirements.txt ./RUN uv pip install --system -r requirements.txt# 安装Playwright浏览器二进制(系统依赖已在上一步安装)RUN python -m playwright install chromium# 复制.envCOPY .env.example .env# 复制应用源代码COPY . .# 确保运行时目录存在,即使构建上下文中被.gitignore忽略RUN mkdir -p /ms-playwright logs final_reports insight_engine_streamlit_reports media_engine_streamlit_reports query_engine_streamlit_reportsEXPOSE 5000 8501 8502 8503# 默认命令启动Flask编排器,该编排器负责启动Streamlit代理CMD ["python", "app.py"]
构建优化策略:
| 阶段 | 优化点 | 说明 |
|---|---|---|
| 基础镜像 | python:3.11-slim |
最小化镜像大小 |
| 系统依赖 | 合并APT命令 | 减少Docker layer |
| Python依赖 | uv pip --system |
快速安装,利用Docker缓存 |
| Playwright | 二进制安装 | 避免编译时间 |
| 源代码 | 最后复制 | 最大化缓存复用 |
二、开发环境配置
2.1 Conda环境管理(推荐)
# 创建Python 3.11环境conda create -n pytorch_python11 python=3.11# 激活环境conda activate pytorch_python11# 安装依赖pip install -r requirements.txt# 安装Playwright浏览器驱动playwright install
为什么选择Conda?
-
依赖隔离:避免与系统Python冲突
-
跨平台:Windows/Linux/macOS统一体验
-
版本管理:精确控制Python版本
2.2 UV环境管理(快速方案)
# 安装uv(如未安装)pip install uv# 创建Python 3.11环境uv venv --python3.11# 激活虚拟环境# Linux/macOSsource .venv/bin/activate# Windows.venv\Scripts\activate# 安装依赖uv pip install -r requirements.txt
UV的优势:
-
安装速度:比pip快10-100倍
-
轻量级:无需Conda的庞大依赖
-
现代设计:支持PEP 621等最新标准
2.3 环境变量配置
# 复制环境变量模板cp .env.example .env# 编辑.env文件vim .env
关键配置项:
| 配置项 | 说明 | 示例 |
|---|---|---|
| 数据库配置 | PostgreSQL/MySQL连接 | DB_HOST=localhostDB_PORT=5432 |
| LLM API配置 | 各Engine的API密钥 | QUERY_ENGINE_API_KEY=sk-... |
| 搜索工具配置 | Tavily/Bocha/Anspire | TAVILY_API_KEY=... |
| GraphRAG配置 | 知识图谱开关 | GRAPHRAG_ENABLED=true |
| 端口配置 | 各服务端口 | HOST=0.0.0.0PORT=5000 |
三、生产环境优化策略
3.1 反向代理与负载均衡
# nginx.conf 示例upstreambettafish {server 127.0.0.1:5001;server 127.0.0.1:5002;server 127.0.0.1:5003;}server {listen 80;server_name bettafish.example.com;# 限流配置limit_req_zone$binary_remote_addr zone=one:10r/s;limit_conn_zone $binary_remote_addr zone=one:10;location / {proxy_passhttp://bettafish;proxy_set_headerHost $host;proxy_set_headerX-Real-IP $remote_addr;proxy_set_headerX-Forwarded-For $proxy_add_x_forwarded_for;# 超时配置proxy_connect_timeout 300s;proxy_send_timeout 300s;proxy_read_timeout 300s; }# 日志配置access_log /var/log/nginx/bettafish_access.log;error_log /var/log/nginx/bettafish_error.log;}
配置要点:
-
限流保护:
limit_req_zone防止单IP过载 -
健康检查:
proxy_next_upstream配置健康检查路径 -
超时控制:避免长时间请求占用资源
-
日志记录:访问日志和错误日志分开
3.2 数据库连接池优化
# InsightEngine/utils/db.pyfromsqlalchemy.ext.asyncioimportcreate_async_engine, AsyncEnginefromsqlalchemy.ext.asyncioimportAsyncSession# 创建异步引擎(配置连接池)engine: AsyncEngine=create_async_engine(build_async_url(),pool_size=20, # 连接池大小max_overflow=10, # 最大溢出连接pool_pre_ping=True, # 连接前Ping检查pool_recycle=3600, # 连接回收时间(1小时)echo=False)asyncdefget_db_session() ->AsyncSession:"""获取数据库会话"""asyncwithengine.connect() asconn:awaitconn.execute(text("SELECT 1"))returnAsyncSession(engine)
连接池参数说明:
| 参数 | 说明 | 推荐值 |
|---|---|---|
| pool_size | 核心连接数 | 20-50 |
| max_overflow | 溢出连接数 | 10-20 |
| pool_pre_ping | 连接前检查 | true |
| pool_recycle | 连接回收时间 | 3600s |
| echo | SQL日志输出 | false(生产环境) |
3.3 缓存策略(Redis)
# utils/cache_manager.pyimportredisimportjsonfromtypingimportOptional, AnyfromloguruimportloggerclassRedisCache:"""Redis缓存管理器"""def__init__(self, redis_url: str="redis://localhost:6379/0"):self.client=redis.from_url(redis_url, decode_responses=True)defget(self, key: str) ->Optional[Any]:"""获取缓存"""try:cached=self.client.get(key)ifcached:returnjson.loads(cached)exceptExceptionase:logger.warning(f"Redis get失败: {e}")returnNonedefset(self, key: str, value: Any, ttl: int=3600) ->bool:"""设置缓存"""try:self.client.setex(key, ttl, json.dumps(value))returnTrueexceptExceptionase:logger.warning(f"Redis set失败: {e}")returnFalsedefdelete(self, key: str) ->bool:"""删除缓存"""try:self.client.delete(key)returnTrueexceptExceptionase:logger.warning(f"Redis delete失败: {e}")returnFalsedefclear_pattern(self, pattern: str) ->int:"""批量删除缓存"""try:keys=self.client.keys(f"{pattern}*")ifkeys:returnself.client.delete(*keys)return0exceptExceptionase:logger.warning(f"Redis clear失败: {e}")return0
缓存策略:
| 数据类型 | TTL | Redis Key模式 | 说明 |
|---|---|---|---|
| 热点新闻 | 3600s | news:hot:* |
1小时缓存 |
| LLM响应 | 1800s | llm:* |
30分钟缓存 |
| 情感分析结果 | 7200s | sentiment:* |
2小时缓存 |
| GraphRAG查询 | 14400s | graphrag:* |
4小时缓存 |
四、监控与日志系统
4.1 Loguru日志配置
# utils/logging_config.pyfromloguruimportloggerimportsysfrompathlibimportPathdefsetup_logging(log_dir: Path=Path("logs")):"""配置日志系统"""# 移除默认handlerlogger.remove()# 控制台日志(INFO级别)logger.add(sys.stderr,format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <level>{message}</level>",level="INFO",colorize=True )# 文件日志(DEBUG级别)logger.add(log_dir/"bettafish_{time:YYYY-MM-DD}.log",rotation="500 MB",retention="30 days",level="DEBUG",format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {name}:{function}:{line} | {message}",compression="zip" )# 错误日志单独文件logger.add(log_dir/"error_{time:YYYY-MM-DD}.log",rotation="100 MB",retention="90 days",level="ERROR",format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {name}:{function}:{line} | {message}",backtrace=True,diagnose=True )
日志策略:
| 日志类型 | 文件 | 级别 | 保留时间 |
|---|---|---|---|
| 应用日志 | bettafish_YYYY-MM-DD.log |
DEBUG | 30天 |
| 错误日志 | error_YYYY-MM-DD.log |
ERROR | 90天 |
| 日志轮转 | 自动 | 500MB/100MB | – |
| 日志压缩 | 自动 | zip | – |
4.2 Prometheus监控集成
# utils/metrics.pyfromprometheus_clientimportCounter, Histogram, Gauge, start_http_server# 定义监控指标request_counter=Counter('api_requests_total', 'Total API requests', ['method', 'endpoint', 'status'])request_duration=Histogram('api_request_duration_seconds', 'API request duration', ['endpoint'])active_connections=Gauge('active_connections', 'Active database connections')# 初始化指标request_counter.labels(method='GET', endpoint='/api/search', status='200').inc()request_duration.labels(endpoint='/api/search').observe(0.5)active_connections.set(10)# 启动Prometheus HTTP服务器start_http_server(8000)
关键监控指标:
| 指标类型 | 说明 | 告警阈值 |
|---|---|---|
| 请求计数 | API请求总数 | – |
| 请求延迟 | API响应时间 | >5s |
| 错误率 | 4xx/5xx错误比例 | >5% |
| 数据库连接 | 活跃连接数 | >80% |
| 内存使用 | 进程内存 | >90% |
4.3 健康检查端点
# app.py 中的健康检查@app.route('/_health')defhealth_check():"""系统健康检查"""health_status= {'status': 'healthy','timestamp': datetime.utcnow().isoformat(),'services': {} }# 检查数据库连接try:fromutils.dbimportget_db_sessionwithget_db_session() assession:session.execute(text("SELECT 1"))health_status['services']['database'] ='healthy'exceptExceptionase:health_status['status'] ='unhealthy'health_status['services']['database'] =f'unhealthy: {str(e)}'# 检查文件系统try:importosforpathin ['logs', 'final_reports', 'ir']:ifnotos.path.exists(path):raiseFileNotFoundError(f"{path} not found")health_status['services']['filesystem'] ='healthy'exceptExceptionase:health_status['status'] ='degraded'health_status['services']['filesystem'] =f'degraded: {str(e)}'# 检查内存try:importpsutilmemory_percent=psutil.virtual_memory().percenthealth_status['services']['memory'] =f"{memory_percent}%"ifmemory_percent>90:health_status['status'] ='warning'exceptExceptionase:health_status['services']['memory'] ='unknown'status_code=200ifhealth_status['status'] =='healthy'else503returnjsonify(health_status), status_code
五、性能调优最佳实践
5.1 数据库查询优化
-- 优化前:全表扫描SELECT*FROM daily_topics ORDERBY created_at DESCLIMIT100;-- 优化后:使用索引和分页SELECT topic_name, keywords, heat_score, created_atFROM daily_topicsWHERE created_at >= DATE_SUB(CURRENT_DATE,INTERVAL30 DAY)ORDERBY heat_score DESC, created_at DESCLIMIT100;
SQL优化策略:
| 优化项 | 优化前 | 优化后 | 提升 |
|---|---|---|---|
| 索引 | 全表扫描 | 走索引 | 10-100x |
| 字段选择 | SELECT * |
只选必需字段 | 2-5x |
| 分页 | 一次查询1000条 | 分页查询 | 5-10x |
| 时间范围 | 查询所有历史 | 30天内 | 3-10x |
5.2 异步I/O优化
# utils/async_helper.pyimportasynciofromtypingimportList, Callable, Anyfromfunctoolsimportwrapsdefasync_wrap(func: Callable) ->Callable:"""异步包装器"""@wraps(func)asyncdefwrapper(*args, **kwargs):# 如果函数不是协程,转为协程ifnotasyncio.iscoroutinefunction(func):returnawaitasyncio.to_thread(func)(*args, **kwargs)returnawaitfunc(*args, **kwargs)returnwrapperasyncdefrun_concurrent(tasks: List[Callable], max_concurrency: int=10) ->List[Any]:"""并发执行多个任务"""semaphore=asyncio.Semaphore(max_concurrency)asyncdeflimited_task(task):asyncwithsemaphore:returnawaittask()returnawaitasyncio.gather(*[limited_task(task) fortaskintasks])
并发控制策略:
| 任务类型 | 最大并发数 | 说明 |
|---|---|---|
| 数据库查询 | 10-20 | 避免连接池耗尽 |
| LLM API调用 | 3-5 | 避免API限流 |
| 文件I/O | 50-100 | 磁盘I/O瓶颈 |
| 网络请求 | 20-30 | 避免被封IP |
5.3 内存优化
# utils/memory_optimization.pyimportgcfromtypingimportIteratordefbatch_process(items: list, batch_size: int=100) ->Iterator[list]:"""批量处理生成器"""foriinrange(0, len(items), batch_size):yielditems[i:i+batch_size]# 使用示例results= []forbatchinbatch_process(large_dataset, batch_size=100):batch_results=process_batch(batch) # 处理100条results.extend(batch_results)delbatch_results# 立即释放内存gc.collect() # 强制垃圾回收
内存优化策略:
| 策略 | 说明 | 效果 |
|---|---|---|
| 分批处理 | 避免一次性加载大数据 | 内存使用↓90% |
| 生成器 | 惰性生成数据 | 内存使用↓80% |
| 及时释放 | 处理完立即del | 内存使用↓30% |
| 强制GC | 关键操作后gc.collect() | 内存回收↑50% |
六、安全性考虑
6.1 API密钥管理
# config.py 中的密钥管理frompydantic_settingsimportBaseSettingsfromtypingimportOptionalclassSettings(BaseSettings):"""全局配置管理"""# API密钥(从环境变量读取,不硬编码)QUERY_ENGINE_API_KEY: strMEDIA_ENGINE_API_KEY: strINSIGHT_ENGINE_API_KEY: strREPORT_ENGINE_API_KEY: strFORUM_HOST_API_KEY: str# .env文件必须在.gitignore中classConfig:env_file=".env"env_prefix=""case_sensitive=Falseextra="allow"def__init__(self, **kwargs):super().__init__(**kwargs)# 验证必需的密钥self._validate_required_keys()def_validate_required_keys(self):"""验证必需的配置项"""required_keys= ['QUERY_ENGINE_API_KEY','MEDIA_ENGINE_API_KEY','INSIGHT_ENGINE_API_KEY','REPORT_ENGINE_API_KEY','FORUM_HOST_API_KEY' ]missing_keys= []forkeyinrequired_keys:ifnotgetattr(self, key, None):missing_keys.append(key)ifmissing_keys:raiseValueError(f"缺少必需的配置项: {', '.join(missing_keys)}")
密钥管理最佳实践:
| 实践 | 说明 |
|---|---|
| 环境变量 | 密钥不在代码中出现 |
| .gitignore | .env文件加入.gitignore |
| 密钥轮换 | 定期更换API密钥 |
| 最小权限 | API密钥只授予必要权限 |
| 审计日志 | 记录密钥使用情况 |
6.2 数据隐私保护
# utils/privacy.pyimportrefromtypingimportOptionalclassPrivacyFilter:"""隐私数据过滤器"""# 敏感信息正则表达式PHONE_PATTERN=r'1[3-9]\d{9}'EMAIL_PATTERN=r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'ID_CARD_PATTERN=r'\b[1-9]\d{5}(18|19|20)\d{2}(0[1-9]\d{3}[0-9Xx])\b'@classmethoddeffilter_phone(cls, text: str) ->str:"""过滤手机号"""returnre.sub(cls.PHONE_PATTERN, '[手机号已隐藏]', text)@classmethoddeffilter_email(cls, text: str) ->str:"""过滤邮箱"""returnre.sub(cls.EMAIL_PATTERN, '[邮箱已隐藏]', text)@classmethoddeffilter_id_card(cls, text: str) ->str:"""过滤身份证号"""returnre.sub(cls.ID_CARD_PATTERN, '[身份证号已隐藏]', text)@classmethoddeffilter_all(cls, text: str) ->str:"""过滤所有敏感信息"""text=cls.filter_phone(text)text=cls.filter_email(text)text=cls.filter_id_card(text)returntext# 使用示例raw_text="联系张三:13812345678,邮箱:zhangsan@example.com"filtered_text=PrivacyFilter.filter_all(raw_text)# 输出:联系张三:[手机号已隐藏],邮箱:[邮箱已隐藏]
6.3 HTTPS强制与证书管理
# nginx.conf HTTPS配置server {listen443 ssl http2;server_name bettafish.example.com;# SSL证书ssl_certificate /etc/letsencrypt/live/bettafish.example.com/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/bettafish.example.com/privkey.pem;# SSL优化ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384';ssl_prefer_server_ciphers on;# HSTSadd_headerStrict-Transport-Security"max-age=63072000; includeSubDomains; preload";location / {proxy_passhttp://bettafish; }}# HTTP重定向到HTTPSserver {listen 80;server_name bettafish.example.com;return301 https://$server_name$request_uri;}
七、CI/CD自动化部署
7.1 GitHub Actions工作流
# .github/workflows/docker_ci.ymlname: Docker Image CIon: push: tags: - 'v*'jobs: build_and_publish: runs-on: ubuntu-latest permissions: contents: read packages: write steps: - name: Checkout repository uses: actions/checkout@v4 - name: Free Disk Space run: | sudo rm -rf /usr/share/dotnet sudo rm -rf /usr/local/lib/android sudo rm -rf /opt/ghc sudo rm -rf /opt/hostedtoolcache/CodeQL sudo docker image prune --all --force df -h - name: Log in to Container registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v5 with: images: ghcr.io/${{ github.repository }} tags: | type=ref,event=tag type=semver,pattern={{version}} type=raw,value=latest - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: driver: docker-container - name: Build and push Docker image uses: docker/build-push-action@v5 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }}# 缓存优化 cache-from: type=gha,mode=max cache-to: type=gha,mode=max platforms: linux/amd64,linux/arm64
CI/CD最佳实践:
| 实践 | 说明 |
|---|---|
| 多架构支持 | linux/amd64 + linux/arm64 |
| 缓存优化 | cache-from/cache-to加速构建 |
| 自动化发布 | push触发自动构建 |
| 磁盘清理 | 释放构建环境磁盘空间 |
八、完整部署流程
8.1 开发环境启动
# 1. 克隆项目git clone https://github.com/666ghj/BettaFish.gitcd BettaFish# 2. 创建并激活Conda环境conda create -n bettafish python=3.11conda activate bettafish# 3. 安装依赖pip install -r requirements.txtplaywright install# 4. 配置环境变量cp .env.example .envvim .env # 编辑API密钥等配置# 5. 启动系统python app.py # 访问 http://localhost:5000
8.2 生产环境部署(Docker)
# 1. 克隆项目git clone https://github.com/666ghj/BettaFish.gitcd BettaFish# 2. 配置环境变量cp .env.example .envvim .env # 配置生产环境的API密钥和数据库连接# 3. 启动Docker Composedocker compose up -d# 4. 查看日志docker compose logs -f bettafish# 5. 健康检查curl http://localhost:5000/_health
8.3 生产环境部署(Kubernetes)
# k8s/deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: bettafishspec: replicas: 3 selector: matchLabels: app: bettafish template: metadata: labels: app: bettafish spec: containers: - name: bettafish image: ghcr.io/666ghj/bettafish:latest ports: - containerPort: 5000 env: - name: PYTHONUNBUFFERED value: "1" - name: DB_HOST valueFrom: configMapKeyRef: name: bettafish-config key: db-host resources: requests: memory: "512Mi" cpu: "500m" limits: memory: "1Gi" cpu: "1000m" livenessProbe: httpGet: path: /_health port: 5000 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /_health port: 5000 initialDelaySeconds: 10 periodSeconds: 5---apiVersion: v1kind: Servicemetadata: name: bettafishspec: selector: matchLabels: app: bettafish ports: - protocol: TCP port: 80 targetPort: 5000 type: LoadBalancer
K8s部署优势:
| 特性 | Docker Compose | Kubernetes |
|---|---|---|
| 自动扩缩容 | ❌ | ✅ |
| 滚动更新 | ❌ | ✅ |
| 服务发现 | ❌ | ✅ |
| 资源限制 | ✅ | ✅ |
| 多节点 | ❌ | ✅ |
九、故障排查与维护
9.1 常见问题排查
| 问题 | 排查步骤 | 解决方案 |
|---|---|---|
| 端口冲突 | netstat -tulpn检查端口占用 |
修改.env中的PORT配置 |
| 内存不足 | docker stats查看容器资源 |
增加内存限制,优化代码 |
| 数据库连接失败 | docker compose logs db查看日志 |
检查.env中的数据库配置 |
| LLM API调用失败 | 查看logs/bettafish_*.log |
检查API密钥和额度 |
9.2 日志分析技巧
# 查看错误日志grep"ERROR" logs/bettafish_*.log# 查找特定错误grep"ConnectionError" logs/bettafish_*.log# 统计错误数量grep-c"ERROR" logs/bettafish_*.log# 查找慢查询grep"duration" logs/bettafish_*.log | awk-F'duration=''{print $2}' | sort-rn | head -10
十、总结:BettaFish工程实践的核心思想
10.1 核心设计原则
-
容器化部署:Docker Compose/K8s,环境一致性
-
监控先行:日志、Prometheus、健康检查
-
性能优化:连接池、缓存、异步I/O、分批处理
-
安全第一:密钥管理、隐私过滤、HTTPS
-
自动化部署:CI/CD流水线、自动发布
-
可观测性:结构化日志、指标收集、链路追踪
10.2 适用场景
✅ 适合:
-
需要生产级部署的多Agent AI系统
-
需要高可用、可扩展的架构
-
需要完善监控和告警的系统
-
需要自动化部署流程的项目
❌ 不适合:
-
小型个人项目(Docker Compose即可)
-
单机部署场景(Docker即可)
-
开发环境测试(本地运行即可)
系列文章总结
| 序号 | 篇名 | 篇幅 | 核心创新 |
|---|---|---|---|
| 1 | 整体架构设计 | 117行 | Flask+Streamlit混合架构、Agent论坛机制 |
| 2 | Agent论坛机制 | 494行 | 论坛日志作为共享媒介、LLM主持人设计 |
| 3 | GraphRAG知识图谱 | 509行 | 基于结构化数据的图谱构建、5种节点类型 |
| 4 | 报告生成引擎 | 620行 | IR中间表示、模板驱动、流式生成+自动修复 |
| 5 | 分布式爬虫系统 | 711行 | 两阶段设计、7大平台Playwright爬虫 |
| 6 | 情感分析模型层 | 712行 | 多模型融合策略、BERT/GPT-2/Qwen3微调 |
| 7 | 工程实践与部署 | 800+行 | Docker部署、监控优化、安全考虑 |
总篇幅:约4000行,全面覆盖BettaFish从设计到部署的完整技术栈!
系列文章完成! 🎉
BettaFish(微舆)作为一个多智能体舆情分析系统,从架构设计到工程实践,展示了如何构建一个生产级的AI应用。希望这7篇文章能为你提供有价值的参考。
夜雨聆风
