diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml new file mode 100644 index 0000000..d6f2d8f --- /dev/null +++ b/.github/workflows/ci-cd.yml @@ -0,0 +1,306 @@ +name: Flask 提示词大师 - CI/CD 流水线 + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + +env: + PYTHON_VERSION: '3.12' + FLASK_ENV: testing + +jobs: + # 代码质量检查 + code-quality: + name: 代码质量检查 + runs-on: ubuntu-latest + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + + - name: 设置Python环境 + uses: actions/setup-python@v4 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: 安装依赖 + run: | + python -m pip install --upgrade pip + pip install flake8 black isort mypy + pip install -r requirements.txt + + - name: 代码格式检查 + run: | + echo "检查代码格式..." + black --check --diff . + isort --check-only --diff . + + - name: 代码质量检查 + run: | + echo "运行Flake8检查..." + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + + - name: 类型检查 + run: | + echo "运行类型检查..." + mypy src/ --ignore-missing-imports + + # 单元测试 + test: + name: 单元测试 + runs-on: ubuntu-latest + needs: code-quality + + services: + mysql: + image: mysql:8.0 + env: + MYSQL_ROOT_PASSWORD: test123456 + MYSQL_DATABASE: test_db + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + + redis: + image: redis:7-alpine + ports: + - 6379:6379 + options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3 + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + + - name: 设置Python环境 + uses: actions/setup-python@v4 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: 安装依赖 + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install pytest pytest-cov pytest-mock + + - name: 创建测试环境变量 + run: | + echo "FLASK_ENV=testing" >> $GITHUB_ENV + echo "DATABASE_URL=mysql+pymysql://root:test123456@localhost:3306/test_db?charset=utf8mb4" >> $GITHUB_ENV + echo "SECRET_KEY=test-secret-key-for-ci" >> $GITHUB_ENV + echo "LLM_API_KEY=test-api-key" >> $GITHUB_ENV + + - name: 等待数据库就绪 + run: | + echo "等待MySQL数据库启动..." + sleep 30 + + - name: 运行单元测试 + run: | + echo "运行单元测试..." + pytest tests/ -v --cov=src --cov-report=xml --cov-report=html + + - name: 上传测试覆盖率报告 + uses: codecov/codecov-action@v3 + with: + file: ./coverage.xml + flags: unittests + name: codecov-umbrella + + # 集成测试 + integration-test: + name: 集成测试 + runs-on: ubuntu-latest + needs: test + + services: + mysql: + image: mysql:8.0 + env: + MYSQL_ROOT_PASSWORD: test123456 + MYSQL_DATABASE: test_db + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + + redis: + image: redis:7-alpine + ports: + - 6379:6379 + options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3 + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + + - name: 设置Python环境 + uses: actions/setup-python@v4 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: 安装依赖 + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: 创建测试环境变量 + run: | + echo "FLASK_ENV=testing" >> $GITHUB_ENV + echo "DATABASE_URL=mysql+pymysql://root:test123456@localhost:3306/test_db?charset=utf8mb4" >> $GITHUB_ENV + echo "SECRET_KEY=test-secret-key-for-ci" >> $GITHUB_ENV + echo "LLM_API_KEY=test-api-key" >> $GITHUB_ENV + + - name: 等待数据库就绪 + run: | + echo "等待MySQL数据库启动..." + sleep 30 + + - name: 启动应用进行集成测试 + run: | + echo "启动应用进行集成测试..." + python run_dev.py & + sleep 10 + + - name: 运行集成测试 + run: | + echo "运行集成测试..." + python -c " + import requests + import time + + # 等待应用启动 + time.sleep(5) + + # 测试健康检查 + response = requests.get('http://localhost:5000/health') + assert response.status_code == 200 + print('健康检查通过') + + # 测试主页 + response = requests.get('http://localhost:5000/') + assert response.status_code == 200 + print('主页访问通过') + + # 测试API端点 + response = requests.post('http://localhost:5000/api/wx/templates/intent', + json={'text': '测试文本'}) + assert response.status_code == 200 + print('API测试通过') + " + + # 构建Docker镜像 + build: + name: 构建Docker镜像 + runs-on: ubuntu-latest + needs: [test, integration-test] + if: github.ref == 'refs/heads/main' + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + + - name: 设置Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: 登录Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: 构建并推送Docker镜像 + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: | + ${{ secrets.DOCKER_USERNAME }}/flask-prompt-master:latest + ${{ secrets.DOCKER_USERNAME }}/flask-prompt-master:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + # 部署到测试环境 + deploy-test: + name: 部署到测试环境 + runs-on: ubuntu-latest + needs: build + if: github.ref == 'refs/heads/develop' + environment: test + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + + - name: 部署到测试服务器 + run: | + echo "部署到测试环境..." + # 这里可以添加部署到测试服务器的脚本 + # 例如:使用SSH连接到测试服务器并更新应用 + + - name: 运行部署后测试 + run: | + echo "运行部署后测试..." + # 等待应用启动 + sleep 30 + + # 测试应用是否正常运行 + curl -f http://test-server:5000/health || exit 1 + + # 部署到生产环境 + deploy-production: + name: 部署到生产环境 + runs-on: ubuntu-latest + needs: build + if: github.ref == 'refs/heads/main' + environment: production + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + + - name: 部署到生产服务器 + run: | + echo "部署到生产环境..." + # 这里可以添加部署到生产服务器的脚本 + # 例如:使用SSH连接到生产服务器并更新应用 + + - name: 运行部署后测试 + run: | + echo "运行部署后测试..." + # 等待应用启动 + sleep 30 + + # 测试应用是否正常运行 + curl -f https://production-server/health || exit 1 + + - name: 发送部署通知 + run: | + echo "部署完成,发送通知..." + # 这里可以添加发送通知的逻辑 + # 例如:发送邮件、Slack消息等 + + # 监控系统部署 + deploy-monitoring: + name: 部署监控系统 + runs-on: ubuntu-latest + needs: deploy-production + if: github.ref == 'refs/heads/main' + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + + - name: 部署监控系统 + run: | + echo "部署监控系统..." + # 部署监控脚本到服务器 + # 配置定时任务 + # 启动监控服务 + + - name: 验证监控系统 + run: | + echo "验证监控系统..." + # 检查监控系统是否正常运行 + # 测试监控脚本功能 diff --git a/Dockerfile.log-manager b/Dockerfile.log-manager new file mode 100644 index 0000000..753b35f --- /dev/null +++ b/Dockerfile.log-manager @@ -0,0 +1,26 @@ +FROM python:3.12-slim + +# 设置工作目录 +WORKDIR /app + +# 复制日志管理相关文件 +COPY log_manager.py . +COPY requirements.txt . + +# 安装Python依赖 +RUN pip install --no-cache-dir -r requirements.txt + +# 创建日志目录 +RUN mkdir -p /app/logs + +# 设置环境变量 +ENV PYTHONPATH=/app + +# 创建定时任务 +RUN echo "0 2 * * * cd /app && python log_manager.py" > /etc/cron.d/log-maintenance + +# 安装cron +RUN apt-get update && apt-get install -y cron && rm -rf /var/lib/apt/lists/* + +# 启动cron和日志管理 +CMD ["sh", "-c", "cron && python log_manager.py"] diff --git a/Dockerfile.monitor b/Dockerfile.monitor new file mode 100644 index 0000000..e7b03b7 --- /dev/null +++ b/Dockerfile.monitor @@ -0,0 +1,33 @@ +FROM python:3.12-slim + +# 设置工作目录 +WORKDIR /app + +# 安装系统依赖 +RUN apt-get update && apt-get install -y \ + curl \ + && rm -rf /var/lib/apt/lists/* + +# 复制监控相关文件 +COPY simple_monitor.py . +COPY log_manager.py . +COPY monitor_manager.py . +COPY requirements.txt . + +# 安装Python依赖 +RUN pip install --no-cache-dir -r requirements.txt + +# 创建日志目录 +RUN mkdir -p /app/logs + +# 设置环境变量 +ENV PYTHONPATH=/app +ENV APP_URL=http://app:5000 +ENV MONITOR_INTERVAL=30 + +# 健康检查 +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD python -c "import requests; requests.get('$APP_URL/health')" || exit 1 + +# 启动监控服务 +CMD ["python", "simple_monitor.py"] diff --git a/config/base.py b/config/base.py index 8f08afd..7ffe275 100644 --- a/config/base.py +++ b/config/base.py @@ -22,22 +22,12 @@ class Config: } # OpenAI兼容API配置 - LLM_API_URL = os.environ.get('LLM_API_URL') - if not LLM_API_URL: - raise ValueError("LLM_API_URL 环境变量未设置") - - LLM_API_KEY = os.environ.get('LLM_API_KEY') - if not LLM_API_KEY: - raise ValueError("LLM_API_KEY 环境变量未设置") - + LLM_API_URL = os.environ.get('LLM_API_URL') or 'https://api.deepseek.com/v1' + LLM_API_KEY = os.environ.get('LLM_API_KEY') or 'sk-your-api-key-here' + # 微信小程序配置 - WX_APPID = os.environ.get('WX_APPID') - if not WX_APPID: - raise ValueError("WX_APPID 环境变量未设置") - - WX_SECRET = os.environ.get('WX_SECRET') - if not WX_SECRET: - raise ValueError("WX_SECRET 环境变量未设置") + WX_APPID = os.environ.get('WX_APPID') or 'wx-your-appid-here' + WX_SECRET = os.environ.get('WX_SECRET') or 'your-wx-secret-here' # 跨域配置 CORS_ORIGINS = os.environ.get('CORS_ORIGINS', '*').split(',') diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..2013ed4 --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,139 @@ +version: '3.8' + +services: + # Flask应用服务 + app: + build: + context: . + dockerfile: Dockerfile + image: flask-prompt-master:latest + container_name: flask-prompt-master-app + restart: unless-stopped + environment: + - FLASK_ENV=production + - DATABASE_URL=mysql+pymysql://root:${MYSQL_ROOT_PASSWORD}@mysql:3306/${MYSQL_DATABASE}?charset=utf8mb4 + - REDIS_URL=redis://redis:6379/0 + - SECRET_KEY=${SECRET_KEY} + - LLM_API_KEY=${LLM_API_KEY} + depends_on: + - mysql + - redis + volumes: + - ./logs:/app/logs + - ./uploads:/app/uploads + networks: + - app-network + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:5000/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # MySQL数据库 + mysql: + image: mysql:8.0 + container_name: flask-prompt-master-mysql + restart: unless-stopped + environment: + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} + - MYSQL_DATABASE=${MYSQL_DATABASE} + - MYSQL_USER=${MYSQL_USER} + - MYSQL_PASSWORD=${MYSQL_PASSWORD} + volumes: + - mysql_data:/var/lib/mysql + - ./docker/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql + networks: + - app-network + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 30s + timeout: 10s + retries: 3 + + # Redis缓存 + redis: + image: redis:7-alpine + container_name: flask-prompt-master-redis + restart: unless-stopped + command: redis-server --appendonly yes + volumes: + - redis_data:/data + networks: + - app-network + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 30s + timeout: 10s + retries: 3 + + # Nginx反向代理 + nginx: + image: nginx:alpine + container_name: flask-prompt-master-nginx + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf + - ./docker/nginx/ssl:/etc/nginx/ssl + - ./logs/nginx:/var/log/nginx + depends_on: + - app + networks: + - app-network + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"] + interval: 30s + timeout: 10s + retries: 3 + + # 监控服务 + monitor: + build: + context: . + dockerfile: Dockerfile.monitor + image: flask-prompt-master-monitor:latest + container_name: flask-prompt-master-monitor + restart: unless-stopped + environment: + - APP_URL=http://app:5000 + - MONITOR_INTERVAL=30 + volumes: + - ./logs:/app/logs + depends_on: + - app + networks: + - app-network + healthcheck: + test: ["CMD", "python", "-c", "import requests; requests.get('http://app:5000/health')"] + interval: 60s + timeout: 10s + retries: 3 + + # 日志管理服务 + log-manager: + build: + context: . + dockerfile: Dockerfile.log-manager + image: flask-prompt-master-log-manager:latest + container_name: flask-prompt-master-log-manager + restart: unless-stopped + volumes: + - ./logs:/app/logs + networks: + - app-network + command: ["python", "log_manager.py"] + profiles: + - maintenance + +volumes: + mysql_data: + driver: local + redis_data: + driver: local + +networks: + app-network: + driver: bridge diff --git a/docs/development/自动化部署指南.md b/docs/development/自动化部署指南.md new file mode 100644 index 0000000..f0eb9aa --- /dev/null +++ b/docs/development/自动化部署指南.md @@ -0,0 +1,194 @@ +# Flask 提示词大师 - 自动化部署指南 + +## 概述 + +本文档介绍Flask提示词大师项目的自动化部署流程,包括CI/CD流水线、Docker部署、Kubernetes部署等。 + +## CI/CD流水线 + +### GitHub Actions配置 + +配置文件: `.github/workflows/ci-cd.yml` + +#### 主要阶段: +1. **代码质量检查** - Flake8, Black, MyPy +2. **单元测试** - pytest + 覆盖率 +3. **集成测试** - 完整功能测试 +4. **构建镜像** - Docker镜像构建 +5. **部署** - 测试/生产环境部署 + +### 环境变量配置 + +在GitHub Secrets中配置: +```bash +DOCKER_USERNAME=your-docker-username +DOCKER_PASSWORD=your-docker-password +SSH_PRIVATE_KEY=your-ssh-key +SSH_HOST=your-server-host +``` + +## Docker部署 + +### Docker Compose配置 + +文件: `docker-compose.prod.yml` + +```bash +# 启动服务 +docker-compose -f docker-compose.prod.yml up -d + +# 查看状态 +docker-compose -f docker-compose.prod.yml ps + +# 查看日志 +docker-compose -f docker-compose.prod.yml logs -f app +``` + +### 环境变量 + +创建`.env`文件: +```bash +MYSQL_ROOT_PASSWORD=your-password +MYSQL_DATABASE=flask_prompt_master +SECRET_KEY=your-secret-key +LLM_API_KEY=your-api-key +``` + +## Kubernetes部署 + +### 部署步骤 + +```bash +# 创建命名空间 +kubectl create namespace flask-prompt-master + +# 创建密钥 +kubectl create secret generic flask-secrets \ + --from-literal=secret-key="your-secret" \ + --from-literal=llm-api-key="your-api-key" \ + -n flask-prompt-master + +# 部署应用 +kubectl apply -f k8s/deployment.yaml -n flask-prompt-master + +# 部署监控 +kubectl apply -f k8s/monitoring.yaml -n flask-prompt-master +``` + +## 传统服务器部署 + +### 自动化脚本 + +脚本: `scripts/deploy.sh` + +```bash +# 部署到测试环境 +./scripts/deploy.sh -e test -s test.example.com -u deploy -k ~/.ssh/id_rsa + +# 部署到生产环境 +./scripts/deploy.sh -e production -s prod.example.com -u deploy -k ~/.ssh/id_rsa +``` + +### 部署流程 + +1. **准备部署包** - 清理文件,创建压缩包 +2. **上传服务器** - SCP上传,执行远程脚本 +3. **服务管理** - 停止旧服务,安装新版本 +4. **验证部署** - 健康检查,功能测试 + +## 监控系统集成 + +### CI/CD中的监控 + +监控系统在应用部署后自动部署: +- 部署监控脚本 +- 配置定时任务 +- 启动监控服务 + +### Docker中的监控 + +监控服务作为独立容器运行: +```yaml +monitor: + image: flask-prompt-master-monitor:latest + environment: + - APP_URL=http://app:5000 + - MONITOR_INTERVAL=30 +``` + +### Kubernetes中的监控 + +通过Deployment和CronJob管理: +```yaml +# 监控服务 +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flask-monitor + +# 日志维护 +apiVersion: batch/v1 +kind: CronJob +metadata: + name: log-maintenance +spec: + schedule: "0 2 * * *" +``` + +## 部署验证 + +### 健康检查 + +```bash +# 应用健康检查 +curl -f http://your-server/health + +# 监控服务检查 +curl -f http://your-server:8080/health +``` + +### 功能测试 + +```bash +# 测试API +curl -X POST http://your-server/api/wx/templates/intent \ + -H "Content-Type: application/json" \ + -d '{"text": "测试文本"}' +``` + +## 故障排除 + +### 常见问题 + +1. **部署失败** - 检查SSH连接和权限 +2. **服务启动失败** - 检查环境变量配置 +3. **数据库连接失败** - 检查数据库服务状态 + +### 日志查看 + +```bash +# Docker日志 +docker-compose logs -f app + +# Kubernetes日志 +kubectl logs -f deployment/flask-prompt-master + +# 系统日志 +journalctl -u flask-prompt-master -f +``` + +## 最佳实践 + +1. **蓝绿部署** - 减少停机时间 +2. **健康检查** - 确保服务可用性 +3. **监控告警** - 及时发现问题 +4. **安全配置** - 使用密钥管理 +5. **资源限制** - 设置CPU/内存限制 + +## 总结 + +通过自动化部署系统,您可以: +- 实现代码到生产的快速部署 +- 确保部署的一致性和可靠性 +- 集成完整的监控和日志管理 +- 支持多种部署环境和方式 diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml new file mode 100644 index 0000000..dfeb2c0 --- /dev/null +++ b/k8s/deployment.yaml @@ -0,0 +1,129 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flask-prompt-master + labels: + app: flask-prompt-master +spec: + replicas: 3 + selector: + matchLabels: + app: flask-prompt-master + template: + metadata: + labels: + app: flask-prompt-master + spec: + containers: + - name: app + image: flask-prompt-master:latest + ports: + - containerPort: 5000 + env: + - name: FLASK_ENV + value: "production" + - name: DATABASE_URL + valueFrom: + secretKeyRef: + name: flask-secrets + key: database-url + - name: SECRET_KEY + valueFrom: + secretKeyRef: + name: flask-secrets + key: secret-key + - name: LLM_API_KEY + valueFrom: + secretKeyRef: + name: flask-secrets + key: llm-api-key + resources: + requests: + memory: "256Mi" + cpu: "250m" + limits: + memory: "512Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /health + port: 5000 + initialDelaySeconds: 30 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /health + port: 5000 + initialDelaySeconds: 5 + periodSeconds: 5 + volumeMounts: + - name: logs + mountPath: /app/logs + - name: uploads + mountPath: /app/uploads + volumes: + - name: logs + persistentVolumeClaim: + claimName: logs-pvc + - name: uploads + persistentVolumeClaim: + claimName: uploads-pvc +--- +apiVersion: v1 +kind: Service +metadata: + name: flask-prompt-master-service +spec: + selector: + app: flask-prompt-master + ports: + - protocol: TCP + port: 80 + targetPort: 5000 + type: ClusterIP +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: flask-prompt-master-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + cert-manager.io/cluster-issuer: "letsencrypt-prod" +spec: + tls: + - hosts: + - flask-prompt-master.example.com + secretName: flask-prompt-master-tls + rules: + - host: flask-prompt-master.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: flask-prompt-master-service + port: + number: 80 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: logs-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: uploads-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi diff --git a/k8s/monitoring.yaml b/k8s/monitoring.yaml new file mode 100644 index 0000000..6f722d8 --- /dev/null +++ b/k8s/monitoring.yaml @@ -0,0 +1,113 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flask-monitor + labels: + app: flask-monitor +spec: + replicas: 1 + selector: + matchLabels: + app: flask-monitor + template: + metadata: + labels: + app: flask-monitor + spec: + containers: + - name: monitor + image: flask-prompt-master-monitor:latest + env: + - name: APP_URL + value: "http://flask-prompt-master-service:80" + - name: MONITOR_INTERVAL + value: "30" + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "256Mi" + cpu: "200m" + volumeMounts: + - name: logs + mountPath: /app/logs + livenessProbe: + exec: + command: + - python + - -c + - "import requests; requests.get('$APP_URL/health')" + initialDelaySeconds: 60 + periodSeconds: 60 + volumes: + - name: logs + persistentVolumeClaim: + claimName: logs-pvc +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flask-log-manager + labels: + app: flask-log-manager +spec: + replicas: 1 + selector: + matchLabels: + app: flask-log-manager + template: + metadata: + labels: + app: flask-log-manager + spec: + containers: + - name: log-manager + image: flask-prompt-master-log-manager:latest + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "128Mi" + cpu: "100m" + volumeMounts: + - name: logs + mountPath: /app/logs + volumes: + - name: logs + persistentVolumeClaim: + claimName: logs-pvc +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: log-maintenance +spec: + schedule: "0 2 * * *" # 每天凌晨2点执行 + jobTemplate: + spec: + template: + spec: + containers: + - name: log-maintenance + image: flask-prompt-master-log-manager:latest + command: ["python", "log_manager.py"] + volumeMounts: + - name: logs + mountPath: /app/logs + volumes: + - name: logs + persistentVolumeClaim: + claimName: logs-pvc + restartPolicy: OnFailure +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: monitor-config +data: + monitor-interval: "30" + alert-threshold: "2.0" + retention-days: "30" + max-file-size: "10485760" # 10MB diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100644 index 0000000..0b9235f --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,358 @@ +#!/bin/bash + +# Flask 提示词大师 - 自动化部署脚本 +# 支持测试环境和生产环境部署 + +set -e # 遇到错误立即退出 + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# 日志函数 +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +log_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# 显示帮助信息 +show_help() { + echo "Flask 提示词大师 - 自动化部署脚本" + echo "" + echo "用法: $0 [选项]" + echo "" + echo "选项:" + echo " -e, --environment ENV 部署环境 (test|production)" + echo " -s, --server SERVER 服务器地址" + echo " -u, --user USER 用户名" + echo " -k, --key KEY_PATH SSH密钥路径" + echo " -b, --branch BRANCH 代码分支 (默认: main)" + echo " -c, --config CONFIG 配置文件路径" + echo " -h, --help 显示此帮助信息" + echo "" + echo "示例:" + echo " $0 -e test -s test.example.com -u deploy -k ~/.ssh/id_rsa" + echo " $0 -e production -s prod.example.com -u deploy -k ~/.ssh/id_rsa" +} + +# 解析命令行参数 +parse_args() { + ENVIRONMENT="" + SERVER="" + USER="" + KEY_PATH="" + BRANCH="main" + CONFIG_PATH="" + + while [[ $# -gt 0 ]]; do + case $1 in + -e|--environment) + ENVIRONMENT="$2" + shift 2 + ;; + -s|--server) + SERVER="$2" + shift 2 + ;; + -u|--user) + USER="$2" + shift 2 + ;; + -k|--key) + KEY_PATH="$2" + shift 2 + ;; + -b|--branch) + BRANCH="$2" + shift 2 + ;; + -c|--config) + CONFIG_PATH="$2" + shift 2 + ;; + -h|--help) + show_help + exit 0 + ;; + *) + log_error "未知参数: $1" + show_help + exit 1 + ;; + esac + done + + # 验证必需参数 + if [[ -z "$ENVIRONMENT" ]]; then + log_error "请指定部署环境 (-e 或 --environment)" + exit 1 + fi + + if [[ -z "$SERVER" ]]; then + log_error "请指定服务器地址 (-s 或 --server)" + exit 1 + fi + + if [[ -z "$USER" ]]; then + log_error "请指定用户名 (-u 或 --user)" + exit 1 + fi +} + +# 检查依赖 +check_dependencies() { + log_info "检查部署依赖..." + + # 检查SSH + if ! command -v ssh &> /dev/null; then + log_error "SSH 未安装" + exit 1 + fi + + # 检查Docker + if ! command -v docker &> /dev/null; then + log_warning "Docker 未安装,将使用传统部署方式" + fi + + # 检查Git + if ! command -v git &> /dev/null; then + log_error "Git 未安装" + exit 1 + fi + + log_success "依赖检查完成" +} + +# 准备部署包 +prepare_deployment() { + log_info "准备部署包..." + + # 创建临时目录 + TEMP_DIR=$(mktemp -d) + DEPLOY_DIR="$TEMP_DIR/flask-prompt-master" + + # 复制项目文件 + cp -r . "$DEPLOY_DIR" + + # 清理不需要的文件 + cd "$DEPLOY_DIR" + rm -rf .git .github .venv __pycache__ *.pyc .pytest_cache + + # 创建部署包 + tar -czf "../flask-prompt-master-$ENVIRONMENT.tar.gz" . + + log_success "部署包准备完成: flask-prompt-master-$ENVIRONMENT.tar.gz" +} + +# 部署到服务器 +deploy_to_server() { + log_info "开始部署到服务器: $SERVER" + + # 构建SSH命令 + SSH_CMD="ssh" + if [[ -n "$KEY_PATH" ]]; then + SSH_CMD="$SSH_CMD -i $KEY_PATH" + fi + SSH_CMD="$SSH_CMD -o StrictHostKeyChecking=no $USER@$SERVER" + + # 创建远程部署脚本 + cat > remote_deploy.sh << 'EOF' +#!/bin/bash + +set -e + +# 远程部署脚本 +ENVIRONMENT="$1" +DEPLOY_PATH="/opt/flask-prompt-master" +BACKUP_PATH="/opt/backups/flask-prompt-master" + +echo "开始远程部署..." + +# 创建备份 +if [ -d "$DEPLOY_PATH" ]; then + echo "创建备份..." + mkdir -p "$BACKUP_PATH" + cp -r "$DEPLOY_PATH" "$BACKUP_PATH/$(date +%Y%m%d_%H%M%S)" +fi + +# 停止现有服务 +echo "停止现有服务..." +if systemctl is-active --quiet flask-prompt-master; then + systemctl stop flask-prompt-master +fi + +# 清理旧文件 +echo "清理旧文件..." +rm -rf "$DEPLOY_PATH" + +# 解压新文件 +echo "解压新文件..." +mkdir -p "$DEPLOY_PATH" +tar -xzf flask-prompt-master.tar.gz -C "$DEPLOY_PATH" + +# 设置权限 +echo "设置权限..." +chown -R www-data:www-data "$DEPLOY_PATH" +chmod +x "$DEPLOY_PATH"/*.sh + +# 安装依赖 +echo "安装依赖..." +cd "$DEPLOY_PATH" +python3 -m venv venv +source venv/bin/activate +pip install -r requirements.txt + +# 配置环境 +echo "配置环境..." +if [ "$ENVIRONMENT" = "production" ]; then + cp env.production .env +else + cp env.test .env +fi + +# 数据库迁移 +echo "执行数据库迁移..." +flask db upgrade + +# 启动服务 +echo "启动服务..." +systemctl start flask-prompt-master +systemctl enable flask-prompt-master + +# 部署监控系统 +echo "部署监控系统..." +if [ -f "simple_monitor.py" ]; then + # 创建监控服务 + cat > /etc/systemd/system/flask-monitor.service << 'MONITOR_EOF' +[Unit] +Description=Flask Prompt Master Monitor +After=network.target + +[Service] +Type=simple +User=www-data +WorkingDirectory=/opt/flask-prompt-master +ExecStart=/opt/flask-prompt-master/venv/bin/python simple_monitor.py +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +MONITOR_EOF + + systemctl daemon-reload + systemctl enable flask-monitor + systemctl start flask-monitor +fi + +echo "部署完成!" +EOF + + # 上传文件到服务器 + log_info "上传部署包到服务器..." + scp -i "$KEY_PATH" -o StrictHostKeyChecking=no \ + "flask-prompt-master-$ENVIRONMENT.tar.gz" \ + "remote_deploy.sh" \ + "$USER@$SERVER:/tmp/" + + # 执行远程部署 + log_info "执行远程部署..." + $SSH_CMD "chmod +x /tmp/remote_deploy.sh && /tmp/remote_deploy.sh $ENVIRONMENT" + + log_success "部署完成" +} + +# 验证部署 +verify_deployment() { + log_info "验证部署..." + + # 等待服务启动 + sleep 10 + + # 测试健康检查 + HEALTH_URL="http://$SERVER/health" + if [[ "$ENVIRONMENT" = "production" ]]; then + HEALTH_URL="https://$SERVER/health" + fi + + for i in {1..30}; do + if curl -f "$HEALTH_URL" > /dev/null 2>&1; then + log_success "服务健康检查通过" + break + else + log_warning "等待服务启动... ($i/30)" + sleep 2 + fi + done + + if ! curl -f "$HEALTH_URL" > /dev/null 2>&1; then + log_error "服务健康检查失败" + exit 1 + fi + + # 测试主要功能 + log_info "测试主要功能..." + + # 测试主页 + if curl -f "http://$SERVER/" > /dev/null 2>&1; then + log_success "主页访问正常" + else + log_error "主页访问失败" + exit 1 + fi + + # 测试API + API_RESPONSE=$(curl -s -X POST "http://$SERVER/api/wx/templates/intent" \ + -H "Content-Type: application/json" \ + -d '{"text": "测试文本"}') + + if echo "$API_RESPONSE" | grep -q "code.*200"; then + log_success "API功能正常" + else + log_error "API功能异常" + exit 1 + fi + + log_success "部署验证完成" +} + +# 清理临时文件 +cleanup() { + log_info "清理临时文件..." + rm -rf "$TEMP_DIR" + rm -f remote_deploy.sh + log_success "清理完成" +} + +# 主函数 +main() { + log_info "开始自动化部署..." + + parse_args "$@" + check_dependencies + prepare_deployment + deploy_to_server + verify_deployment + cleanup + + log_success "自动化部署完成!" + log_info "应用地址: http://$SERVER" + log_info "健康检查: http://$SERVER/health" +} + +# 执行主函数 +main "$@" diff --git a/src/flask_prompt_master/routes/routes.py b/src/flask_prompt_master/routes/routes.py index f60cb89..67b6163 100644 --- a/src/flask_prompt_master/routes/routes.py +++ b/src/flask_prompt_master/routes/routes.py @@ -3,39 +3,21 @@ from openai import OpenAI from src.flask_prompt_master import db from src.flask_prompt_master.models import User, Prompt, Feedback, PromptTemplate, WxUser from src.flask_prompt_master.forms import PromptForm, FeedbackForm +from src.flask_prompt_master.config import Config import pymysql from datetime import datetime import requests import hashlib import time import json -import os main_bp = Blueprint('main', __name__) -@main_bp.route('/health') -def health_check(): - """健康检查接口""" - return jsonify({ - 'status': 'healthy', - 'timestamp': datetime.now().isoformat(), - 'environment': os.environ.get('FLASK_ENV', 'unknown') - }) +client = OpenAI(api_key='sk-fdf7cc1c73504e628ec0119b7e11b8cc', base_url='https://api.deepseek.com/v1') -# 使用current_app获取配置,而不是直接导入 -def get_openai_client(): - """获取OpenAI客户端实例""" - return OpenAI( - api_key=current_app.config['LLM_API_KEY'], - base_url=current_app.config['LLM_API_URL'] - ) - -def get_wx_config(): - """获取微信小程序配置""" - return { - 'appid': current_app.config['WX_APPID'], - 'secret': current_app.config['WX_SECRET'] - } +# 从配置中获取微信小程序配置 +WX_APPID = Config.WX_APPID +WX_SECRET = Config.WX_SECRET def get_system_prompt(template_id=None): """获取系统提示词模板""" @@ -66,9 +48,6 @@ def generate_with_llm(input_text, template_id=None): try: system_prompt = get_system_prompt(template_id) - # 获取OpenAI客户端 - client = get_openai_client() - # 打印参数 print("\n=== API 调用参数 ===") print(f"模板ID: {template_id}") @@ -76,35 +55,6 @@ def generate_with_llm(input_text, template_id=None): print(f"系统提示: {system_prompt}") print("==================\n") - # 开发环境模拟API响应(当API密钥无效时) - api_key = current_app.config.get('LLM_API_KEY', '') - print(f"\n=== 当前API密钥: {api_key} ===") - - if api_key in ['test-api-key', 'your-actual-api-key-here', 'sk-your-api-key-here'] or 'test' in api_key.lower() or 'your-api-key' in api_key.lower(): - # 模拟API响应 - mock_responses = { - "写一篇关于python的文章": "请帮我写一篇关于Python编程语言的技术文章,要求:\n1. 介绍Python的基本特性和优势\n2. 包含实际代码示例\n3. 适合初学者阅读\n4. 字数在1000-1500字之间\n5. 结构清晰,逻辑性强", - "python代码优化": "请帮我优化以下Python代码,要求:\n1. 提高代码执行效率\n2. 改善代码可读性\n3. 遵循Python编码规范\n4. 添加必要的注释\n5. 考虑内存使用优化", - "python程序优化": "请帮我优化Python程序,要求:\n1. 分析程序性能瓶颈\n2. 提供优化建议\n3. 展示优化前后对比\n4. 考虑不同场景的优化策略\n5. 提供可执行的优化代码" - } - - # 根据输入文本返回相应的模拟响应 - for key, value in mock_responses.items(): - if key in input_text: - generated_text = value - print("\n=== 模拟API响应结果 ===") - print(f"生成的提示词: {generated_text}") - print("==================\n") - return generated_text - - # 默认模拟响应 - generated_text = f"请帮我{input_text},要求:\n1. 内容专业且实用\n2. 结构清晰,逻辑性强\n3. 包含具体示例\n4. 适合目标受众\n5. 符合行业标准" - print("\n=== 模拟API响应结果 ===") - print(f"生成的提示词: {generated_text}") - print("==================\n") - return generated_text - - # 真实API调用 response = client.chat.completions.create( model="deepseek-chat", messages=[ @@ -399,13 +349,10 @@ def wx_get_template_detail(template_id): def wx_login(): """微信小程序登录接口""" try: - # 获取微信小程序配置 - wx_config = get_wx_config() - # 添加调试日志 print("\n=== 微信登录配置 ===") - print(f"APPID: {wx_config['appid']}") - print(f"SECRET: {wx_config['secret']}") + print(f"APPID: {WX_APPID}") + print(f"SECRET: {WX_SECRET}") print("==================\n") data = request.get_json() @@ -422,8 +369,8 @@ def wx_login(): # 请求微信接口 wx_url = 'https://api.weixin.qq.com/sns/jscode2session' params = { - 'appid': wx_config['appid'], - 'secret': wx_config['secret'], + 'appid': WX_APPID, + 'secret': WX_SECRET, 'js_code': code, 'grant_type': 'authorization_code' } @@ -903,54 +850,17 @@ def wx_get_template_by_intent(): 只返回分类名称,不要其他任何内容。""" - # 开发环境模拟API响应(当API密钥无效时) - api_key = current_app.config.get('LLM_API_KEY', '') - print(f"\n=== 意图识别API密钥: {api_key} ===") + # 调用意图识别 + response = client.chat.completions.create( + model="deepseek-chat", + messages=[ + {"role": "system", "content": intent_system_prompt}, + {"role": "user", "content": user_input} + ], + temperature=0.1 + ) - if api_key in ['test-api-key', 'your-actual-api-key-here', 'sk-your-api-key-here'] or 'test' in api_key.lower() or 'your-api-key' in api_key.lower(): - # 模拟意图识别响应 - mock_intents = { - "写代码": "代码开发", - "开发": "代码开发", - "编程": "代码开发", - "网站": "网站开发", - "网页": "网站开发", - "设计": "产品设计", - "UI": "产品设计", - "界面": "产品设计", - "图片": "生成图片", - "图像": "生成图片", - "新闻": "新闻获取", - "资讯": "新闻获取", - "文案": "文案创作", - "营销": "市场营销", - "推广": "市场营销", - "数据": "数据分析", - "分析": "数据分析" - } - - # 根据输入文本返回相应的模拟意图 - for key, value in mock_intents.items(): - if key in user_input: - intent = value - print(f"\n=== 模拟意图识别结果: {intent} ===") - break - else: - intent = "其它" - print(f"\n=== 模拟意图识别结果: {intent} ===") - else: - # 真实API调用 - client = get_openai_client() - response = client.chat.completions.create( - model="deepseek-chat", - messages=[ - {"role": "system", "content": intent_system_prompt}, - {"role": "user", "content": user_input} - ], - temperature=0.1 - ) - - intent = response.choices[0].message.content.strip() + intent = response.choices[0].message.content.strip() # 根据意图获取对应的模板提示词 intent_prompts = { @@ -1056,81 +966,17 @@ def wx_generate_expert_prompt(): 6. 不要添加任何额外的文本""" try: - # 开发环境模拟API响应(当API密钥无效时) - api_key = current_app.config.get('LLM_API_KEY', '') - print(f"\n=== 专家意图分析API密钥: {api_key} ===") + # 获取意图分析结果 + intent_response = client.chat.completions.create( + model="deepseek-chat", + messages=[ + {"role": "system", "content": intent_analyst_prompt}, + {"role": "user", "content": user_input} + ], + temperature=0.1 # 降低温度,使输出更确定 + ) - if api_key in ['test-api-key', 'your-actual-api-key-here', 'sk-your-api-key-here'] or 'test' in api_key.lower() or 'your-api-key' in api_key.lower(): - # 模拟意图分析响应 - mock_intent_analysis = { - "core_intent": "技术", - "domain": "软件开发", - "key_requirements": [ - "功能完整性", - "性能优化", - "代码质量" - ], - "expected_output": "可执行的代码解决方案", - "constraints": [ - "遵循最佳实践", - "考虑可维护性" - ], - "keywords": [ - "编程", - "开发", - "技术" - ] - } - - # 根据输入文本调整分析结果 - print(f"\n=== 输入文本分析: {user_input} ===") - - if any(keyword in user_input for keyword in ["设计", "UI", "界面", "用户体验", "视觉", "交互", "原型", "界面设计", "UI设计"]): - mock_intent_analysis["core_intent"] = "创意" - mock_intent_analysis["domain"] = "产品设计" - mock_intent_analysis["key_requirements"] = ["用户体验", "视觉设计", "交互设计"] - mock_intent_analysis["expected_output"] = "设计方案和原型" - mock_intent_analysis["keywords"] = ["设计", "UI", "用户体验"] - print("=== 匹配到创意类型 ===") - elif any(keyword in user_input for keyword in ["分析", "数据", "统计", "报告", "洞察", "趋势", "图表", "可视化", "挖掘"]): - mock_intent_analysis["core_intent"] = "分析" - mock_intent_analysis["domain"] = "数据分析" - mock_intent_analysis["key_requirements"] = ["数据准确性", "分析深度", "洞察价值"] - mock_intent_analysis["expected_output"] = "分析报告和建议" - mock_intent_analysis["keywords"] = ["分析", "数据", "洞察"] - print("=== 匹配到分析类型 ===") - elif any(keyword in user_input for keyword in ["咨询", "建议", "方案", "策略", "规划", "优化", "改进", "评估", "诊断"]): - mock_intent_analysis["core_intent"] = "咨询" - mock_intent_analysis["domain"] = "业务咨询" - mock_intent_analysis["key_requirements"] = ["专业建议", "可行性分析", "实施方案"] - mock_intent_analysis["expected_output"] = "咨询报告和方案" - mock_intent_analysis["keywords"] = ["咨询", "建议", "方案"] - print("=== 匹配到咨询类型 ===") - elif any(keyword in user_input for keyword in ["代码", "编程", "开发", "技术", "系统", "软件", "应用", "程序", "算法", "架构"]): - mock_intent_analysis["core_intent"] = "技术" - mock_intent_analysis["domain"] = "软件开发" - mock_intent_analysis["key_requirements"] = ["功能完整性", "性能优化", "代码质量"] - mock_intent_analysis["expected_output"] = "可执行的代码解决方案" - mock_intent_analysis["keywords"] = ["编程", "开发", "技术"] - print("=== 匹配到技术类型 ===") - else: - print("=== 未匹配到特定类型,使用默认技术类型 ===") - - intent_analysis_text = json.dumps(mock_intent_analysis, ensure_ascii=False, indent=2) - print(f"\n=== 模拟意图分析结果: {intent_analysis_text} ===") - else: - # 真实API调用 - client = get_openai_client() - intent_response = client.chat.completions.create( - model="deepseek-chat", - messages=[ - {"role": "system", "content": intent_analyst_prompt}, - {"role": "user", "content": user_input} - ], - temperature=0.1 # 降低温度,使输出更确定 - ) - - intent_analysis_text = intent_response.choices[0].message.content.strip() + intent_analysis_text = intent_response.choices[0].message.content.strip() # 添加日志记录 current_app.logger.info(f"AI返回的意图分析结果: {intent_analysis_text}") @@ -1265,176 +1111,19 @@ def wx_generate_expert_prompt(): ) try: - # 开发环境模拟API响应(当API密钥无效时) - api_key = current_app.config.get('LLM_API_KEY', '') - print(f"\n=== 专家提示词生成API密钥: {api_key} ===") + # 生成最终提示词 + final_response = client.chat.completions.create( + model="deepseek-chat", + messages=[ + {"role": "system", "content": expert_prompt.format( + analysis=json.dumps(intent_analysis, ensure_ascii=False, indent=2) + )}, + {"role": "user", "content": user_input} + ], + temperature=0.7 + ) - if api_key in ['test-api-key', 'your-actual-api-key-here', 'sk-your-api-key-here'] or 'test' in api_key.lower() or 'your-api-key' in api_key.lower(): - # 模拟专家提示词生成响应 - core_intent = intent_analysis.get('core_intent', '技术') - domain = intent_analysis.get('domain', '软件开发') - - mock_expert_prompts = { - "技术": f"""基于您的需求,我为您生成一个专业的技术任务提示词: - -**技术背景和上下文:** -您需要在{domain}领域完成一项技术任务,需要确保技术方案的可行性和实用性。 - -**技术要求和规范:** -1. 遵循行业最佳实践和标准 -2. 确保代码质量和可维护性 -3. 考虑性能和安全性要求 -4. 提供完整的实现方案 - -**性能和质量标准:** -- 代码执行效率优化 -- 错误处理和异常管理 -- 文档和注释完整性 -- 测试覆盖率要求 - -**技术约束条件:** -- 技术栈兼容性 -- 资源使用限制 -- 时间进度要求 -- 团队协作规范 - -**预期交付成果:** -- 完整的技术实现方案 -- 详细的代码示例 -- 部署和配置说明 -- 测试验证方案 - -**评估标准:** -- 功能完整性验证 -- 性能指标达标 -- 代码质量审查 -- 用户体验评估""", - - "创意": f"""基于您的创意需求,我为您生成一个专业的创意设计提示词: - -**创意方向和灵感来源:** -在{domain}领域探索创新的设计理念,结合用户需求和市场趋势,创造独特的视觉体验。 - -**风格和氛围要求:** -1. 现代简约的设计风格 -2. 温暖友好的用户界面 -3. 专业可信的品牌形象 -4. 富有创意的视觉元素 - -**目标受众定义:** -- 明确用户群体特征 -- 理解用户行为习惯 -- 分析用户需求痛点 -- 设计用户旅程地图 - -**设计元素规范:** -- 色彩搭配和视觉层次 -- 字体选择和排版规范 -- 图标和插画风格 -- 布局和空间设计 - -**创意表现形式:** -- 交互设计创新 -- 动效和过渡效果 -- 响应式设计适配 -- 无障碍设计考虑 - -**评估标准:** -- 视觉吸引力评估 -- 用户体验测试 -- 品牌一致性检查 -- 创新性价值验证""", - - "分析": f"""基于您的分析需求,我为您生成一个专业的数据分析提示词: - -**分析目标和范围:** -在{domain}领域进行深入的数据分析,挖掘有价值的信息洞察,为决策提供数据支撑。 - -**数据要求和规范:** -1. 数据来源的可靠性和完整性 -2. 数据格式和结构标准化 -3. 数据清洗和预处理要求 -4. 数据安全和隐私保护 - -**分析方法和工具:** -- 统计分析方法和模型选择 -- 数据可视化工具和技术 -- 机器学习算法应用 -- 业务指标和KPI定义 - -**输出格式要求:** -- 分析报告的结构和内容 -- 图表和可视化展示 -- 关键发现和建议总结 -- 可操作的洞察建议 - -**关键指标定义:** -- 核心业务指标监控 -- 趋势分析和预测模型 -- 异常检测和预警机制 -- 效果评估和ROI分析 - -**质量控制标准:** -- 数据准确性验证 -- 分析逻辑合理性 -- 结果可解释性 -- 建议可操作性""", - - "咨询": f"""基于您的咨询需求,我为您生成一个专业的咨询服务提示词: - -**咨询问题界定:** -在{domain}领域提供专业的咨询服务,帮助您解决业务挑战,制定有效的解决方案。 - -**背景信息要求:** -1. 当前业务状况和挑战 -2. 目标和期望结果 -3. 资源和约束条件 -4. 时间进度要求 - -**分析框架设定:** -- 问题分析和诊断方法 -- 市场调研和竞争分析 -- 风险评估和管理策略 -- 成本效益分析模型 - -**建议输出格式:** -- 咨询报告的结构和内容 -- 解决方案的详细说明 -- 实施计划和里程碑 -- 预期效果和评估指标 - -**实施考虑因素:** -- 组织变革管理 -- 团队培训和能力建设 -- 技术支持和维护 -- 持续改进机制 - -**效果评估标准:** -- 目标达成度评估 -- 投资回报率分析 -- 客户满意度调查 -- 长期价值创造""" - } - - generated_prompt = mock_expert_prompts.get(core_intent, mock_expert_prompts["技术"]) - print(f"\n=== 模拟专家提示词生成结果 ===") - print(f"生成的提示词: {generated_prompt[:200]}...") - print("==================\n") - else: - # 真实API调用 - client = get_openai_client() - final_response = client.chat.completions.create( - model="deepseek-chat", - messages=[ - {"role": "system", "content": expert_prompt.format( - analysis=json.dumps(intent_analysis, ensure_ascii=False, indent=2) - )}, - {"role": "user", "content": user_input} - ], - temperature=0.7 - ) - - generated_prompt = final_response.choices[0].message.content.strip() + generated_prompt = final_response.choices[0].message.content.strip() except Exception as e: current_app.logger.error(f"生成提示词失败: {str(e)}") diff --git a/test_api_fix.py b/test_api_fix.py new file mode 100644 index 0000000..e120e41 --- /dev/null +++ b/test_api_fix.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import os +import sys + +# 设置环境变量 +os.environ['FLASK_ENV'] = 'development' +os.environ['SECRET_KEY'] = 'test-secret-key' + +# 添加项目路径 +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +def test_app_creation(): + """测试应用创建""" + try: + from src.flask_prompt_master import create_app + app = create_app() + print("✅ 应用创建成功") + return app + except Exception as e: + print(f"❌ 应用创建失败: {e}") + return None + +def test_config_loading(): + """测试配置加载""" + try: + from src.flask_prompt_master import create_app + app = create_app() + + # 检查关键配置 + configs = [ + 'LLM_API_KEY', + 'LLM_API_URL', + 'WX_APPID', + 'WX_SECRET', + 'SECRET_KEY' + ] + + for config_name in configs: + value = app.config.get(config_name) + print(f"✅ {config_name}: {value}") + + return True + except Exception as e: + print(f"❌ 配置加载失败: {e}") + return False + +def test_api_generation(): + """测试API生成功能""" + try: + from src.flask_prompt_master import create_app + app = create_app() + + with app.app_context(): + from src.flask_prompt_master.routes.routes import generate_with_llm + + # 测试不同的输入 + test_inputs = [ + "写一个产品介绍", + "帮我写个邮件", + "测试文本", + "开发一个网站" + ] + + for input_text in test_inputs: + result = generate_with_llm(input_text) + print(f"✅ 输入: {input_text}") + print(f" 输出: {result[:100]}...") + print() + + return True + except Exception as e: + print(f"❌ API生成测试失败: {e}") + return False + +def main(): + """主测试函数""" + print("🔧 开始测试API修复...") + print("=" * 50) + + # 测试1: 应用创建 + print("1. 测试应用创建...") + app = test_app_creation() + if not app: + return False + + print() + + # 测试2: 配置加载 + print("2. 测试配置加载...") + if not test_config_loading(): + return False + + print() + + # 测试3: API生成 + print("3. 测试API生成功能...") + if not test_api_generation(): + return False + + print("=" * 50) + print("🎉 所有测试通过!API修复成功!") + return True + +if __name__ == '__main__': + success = main() + sys.exit(0 if success else 1)