大模型应用-进阶核心技能【13课:第二阶段工程化与部署】

第13课:第二阶段工程化与部署

学习目标

  • 掌握AI应用项目的标准目录结构
  • 学会使用FastAPI构建模型服务接口
  • 了解Docker容器化部署和CI/CD基本流程
  • 理解团队协作中的工程化规范

1. 为什么需要工程化?

前几课我们写的代码都是单文件脚本。但真实的设备维修系统需要:

  • 多人协作:前后端、算法工程师并行开发
  • 持续迭代:新增功能不影响已有功能
  • 可靠部署:开发、测试、生产环境一致
  • 可观测性:日志、监控、问题排查

2. 项目标准结构

maintenance-ai/
├── src/                    # 源代码
│   ├── __init__.py
│   ├── main.py             # FastAPI入口
│   ├── config.py           # 配置管理
│   ├── agent/              # Agent模块
│   │   ├── __init__.py
│   │   ├── tools.py        # 工具定义
│   │   └── agent.py        # Agent构建
│   ├── rag/                # RAG模块
│   │   ├── __init__.py
│   │   ├── loader.py       # 文档加载
│   │   └── retriever.py    # 检索逻辑
│   └── models/             # 数据模型
│       └── schemas.py
├── tests/                  # 测试
│   ├── test_agent.py
│   └── test_rag.py
├── configs/                # 配置文件
│   └── settings.yaml
├── knowledge/              # 知识库原始文件
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── .env.example
└── README.md

关键原则

  • src/按功能模块划分子目录,不按文件类型
  • tests/src/平行,测试文件命名test_*.py
  • 敏感配置放.env,不提交到Git
  • knowledge/存放原始文档,向量库自动生成

3. 配置管理

# src/config.py
from dataclasses import dataclass, field
import os

@dataclass
class Settings:
    # API配置 - 从环境变量读取
    openai_api_key: str = field(default_factory=lambda: os.getenv("OPENAI_API_KEY", ""))
    openai_base_url: str = field(default_factory=lambda: os.getenv("OPENAI_BASE_URL", "https://api.deepseek.com"))
    model_name: str = "deepseek-chat"
    embedding_model: str = "text-embedding-3-small"
    # 服务配置
    host: str = "0.0.0.0"
    port: int = 8000
    # RAG配置
    chunk_size: int = 500
    chunk_overlap: int = 50
    top_k: int = 3

settings = Settings()

4. FastAPI服务接口

# src/main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import logging

logging.basicConfig(level=logging.INFO,
                    format="%(asctime)s [%(levelname)s] %(name)s: %(message)s")
logger = logging.getLogger("maintenance_ai")

app = FastAPI(title="设备维修AI助手", version="1.0.0")

class QueryRequest(BaseModel):
    question: str
    session_id: str = "default"

class DiagnoseRequest(BaseModel):
    device_id: str
    fault_description: str
    priority: str = "普通"

@app.post("/diagnose")
async def diagnose(req: DiagnoseRequest):
    logger.info(f"诊断请求: {req.device_id} - {req.fault_description}")
    result = agent_executor.invoke({"input": f"诊断{req.device_id}{req.fault_description}"})
    return {"status": "ok", "diagnosis": result["output"]}

@app.post("/query")
async def query(req: QueryRequest):
    logger.info(f"问答请求: {req.question[:50]}...")
    result = qa_chain({"question": req.question})
    return {"status": "ok", "answer": result["answer"]}

5. Docker容器化

Dockerfile

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]

docker-compose.yml

version: "3.8"
services:
  app:
    build: .
    ports:
      - "8000:8000"
    env_file: .env
    volumes:
      - ./knowledge:/app/knowledge
      - ./chroma_data:/app/chroma_data
    restart: unless-stopped

关键理解

  • volumes挂载知识库目录,容器重建不丢数据
  • env_file.env读取API Key等敏感配置
  • restart: unless-stopped保证服务自动重启

6. CI/CD基本流程

代码提交 → 自动测试 → 代码审查 → 构建镜像 → 部署测试 → 验证 → 部署生产

最小可用的GitHub Actions配置:

name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: {python-version: "3.11"}
      - run: pip install -r requirements.txt
      - run: pytest tests/

7. 日志与监控

import logging
import time

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(name)s: %(message)s"
)
logger = logging.getLogger("maintenance_ai")

# 在关键操作前后记录日志
logger.info(f"收到诊断请求: device={req.device_id}")
start = time.time()
result = agent_executor.invoke(...)
elapsed = time.time() - start
logger.info(f"诊断完成, 耗时: {elapsed:.1f}s")

日志级别使用规范

  • DEBUG:调试信息,生产环境关闭
  • INFO:正常操作记录(请求、完成、耗时)
  • WARNING:异常但可继续(重试、降级)
  • ERROR:错误需要关注(API失败、数据异常)

8. 团队协作规范

  • Git分支策略:main(生产) → develop(开发) → feature/*(功能)
  • 代码审查:所有代码必须PR审核
  • 接口文档:FastAPI自动生成Swagger文档(/docs)
  • 环境变量:使用.env.example模板,确保团队成员知道需要哪些配置

9. 练习

  1. 基础:运行脚本生成项目脚手架,浏览生成的目录结构,理解每个文件的用途
  2. 进阶:修改生成的main.py,添加一个/health健康检查接口和一个/stats统计接口
  3. 挑战:编写docker-compose.yml加入Redis作为对话缓存服务

10. 验证清单

  • 能画出项目的标准目录结构并说明每个目录的作用
  • 理解FastAPI接口的设计思路和Pydantic模型的作用
  • 能解释Dockerfile中每条指令的作用
  • 知道CI/CD流程的各个环节及其目的
  • 能配置基本的日志记录

code

# -*- coding: utf-8 -*-
"""
第13课:项目脚手架生成器 - 设备维修AI系统
依赖: 无额外依赖(纯Python标准库)
运行后会生成完整的项目目录结构
"""
import os

PROJECT_NAME = "maintenance-ai"

# === 文件模板定义 ===

MAIN_PY = '''\
"""设备维修AI助手 - FastAPI服务"""
import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from src.config import settings

logging.basicConfig(level=logging.INFO,
                    format="%(asctime)s [%(levelname)s] %(name)s: %(message)s")
logger = logging.getLogger("maintenance_ai")


# --- 请求/响应模型 ---
class QueryRequest(BaseModel):
    question: str
    session_id: str = "default"


class DiagnoseRequest(BaseModel):
    device_id: str
    fault_description: str
    priority: str = "普通"


class ReportRequest(BaseModel):
    device_id: str
    report_type: str = "状态报告"


class AIResponse(BaseModel):
    status: str
    data: str
    session_id: str = ""


# --- Agent初始化占位 ---
agent_executor = None  # 实际项目中在此初始化Agent


@asynccontextmanager
async def lifespan(app: FastAPI):
    """应用生命周期管理"""
    logger.info("设备维修AI系统启动...")
    # global agent_executor
    # agent_executor = build_agent()
    yield
    logger.info("设备维修AI系统关闭")


app = FastAPI(title="设备维修AI助手", version="1.0.0", lifespan=lifespan)


@app.get("/health")
async def health():
    return {"status": "ok", "version": "1.0.0"}


@app.post("/diagnose", response_model=AIResponse)
async def diagnose(req: DiagnoseRequest):
    """设备故障诊断接口"""
    logger.info(f"诊断请求: {req.device_id} - {req.fault_description}")
    if not agent_executor:
        raise HTTPException(503, "Agent未初始化")
    result = agent_executor.invoke(
        {"input": f"诊断设备{req.device_id}:{req.fault_description}"}
    )
    return AIResponse(status="ok", data=result["output"])


@app.post("/query", response_model=AIResponse)
async def query(req: QueryRequest):
    """知识库问答接口"""
    logger.info(f"问答请求: {req.question[:50]}...")
    return AIResponse(status="ok", data="接口已就绪,请接入RAG链",
                      session_id=req.session_id)


@app.post("/report", response_model=AIResponse)
async def report(req: ReportRequest):
    """生成设备报告接口"""
    logger.info(f"报告请求: {req.device_id} - {req.report_type}")
    return AIResponse(status="ok",
                      data=f"设备{req.device_id}的{req.report_type}生成中...")


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host=settings.host, port=settings.port)
'''

CONFIG_PY = '''\
"""配置管理模块 - 从环境变量读取配置"""
import os
from dataclasses import dataclass, field


@dataclass
class Settings:
    """应用配置"""
    # API配置
    openai_api_key: str = field(
        default_factory=lambda: os.getenv("OPENAI_API_KEY", ""))
    openai_base_url: str = field(
        default_factory=lambda: os.getenv("OPENAI_BASE_URL", "https://api.deepseek.com"))
    model_name: str = "deepseek-chat"
    embedding_model: str = "text-embedding-3-small"
    # 服务配置
    host: str = "0.0.0.0"
    port: int = 8000
    # RAG配置
    chunk_size: int = 500
    chunk_overlap: int = 50
    top_k: int = 3
    chroma_dir: str = "./chroma_data"


settings = Settings()
'''

SCHEMAS_PY = '''\
"""数据模型定义"""
from pydantic import BaseModel


class Device(BaseModel):
    device_id: str
    name: str
    model: str
    status: str
    run_hours: int
    location: str


class WorkOrder(BaseModel):
    order_id: str
    device_id: str
    fault_description: str
    priority: str
    status: str
    created_at: str
'''

DOCKERFILE = """\
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

COPY . .

EXPOSE 8000

CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
"""

DOCKER_COMPOSE = """\
version: '3.8'

services:
  maintenance-ai:
    build: .
    container_name: maintenance-ai
    ports:
      - "8000:8000"
    env_file:
      - .env
    volumes:
      - ./knowledge:/app/knowledge
      - ./chroma_data:/app/chroma_data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
"""

REQUIREMENTS = """\
fastapi==0.109.0
uvicorn==0.27.0
pydantic==2.5.3
langchain==0.1.0
langchain-openai==0.0.5
langchain-community==0.0.13
chromadb==0.4.22
sentence-transformers==2.3.1
python-dotenv==1.0.0
"""

ENV_EXAMPLE = """\
# OpenAI/DeepSeek API配置
OPENAI_API_KEY=sk-your-api-key-here
OPENAI_BASE_URL=https://api.deepseek.com

# 服务配置
HOST=0.0.0.0
PORT=8000

# 知识库配置
CHUNK_SIZE=500
CHUNK_OVERLAP=50
TOP_K=3
"""

SETTINGS_YAML = """\
# 设备维修AI系统配置
app:
  name: maintenance-ai
  version: 1.0.0

llm:
  model: deepseek-chat
  temperature: 0
  base_url: https://api.deepseek.com

rag:
  chunk_size: 500
  chunk_overlap: 50
  top_k: 3
  embedding_model: text-embedding-3-small

server:
  host: 0.0.0.0
  port: 8000
"""

README = """\
# 设备维修AI助手

## 快速开始

1. 复制配置文件并填入API Key:
   cp .env.example .env

2. 安装依赖:
   pip install -r requirements.txt

3. 启动服务:
   python -m src.main

4. Docker部署:
   docker-compose up -d

## API文档
启动后访问 http://localhost:8000/docs 查看Swagger文档
"""

# === 文件清单 ===
FILES = {
    "src/__init__.py": "# 设备维修AI系统\n__version__ = '1.0.0'\n",
    "src/main.py": MAIN_PY,
    "src/config.py": CONFIG_PY,
    "src/agent/__init__.py": "",
    "src/agent/tools.py": "# 参考第12课的5个工具定义\n# from langchain_classic.tools import tool\n",
    "src/agent/agent.py": "# 参考第12课的build_agent函数\n",
    "src/rag/__init__.py": "",
    "src/rag/loader.py": "# 参考第11课的文档加载逻辑\n",
    "src/rag/retriever.py": "# 参考第11课的向量检索逻辑\n",
    "src/models/__init__.py": "",
    "src/models/schemas.py": SCHEMAS_PY,
    "tests/test_agent.py": "# Agent模块测试\ndef test_placeholder():\n    assert True\n",
    "tests/test_rag.py": "# RAG模块测试\ndef test_placeholder():\n    assert True\n",
    "configs/settings.yaml": SETTINGS_YAML,
    "knowledge/README.md": "# 知识库文件\n将设备维修手册、故障记录等文件放在此目录\n",
    "requirements.txt": REQUIREMENTS,
    "Dockerfile": DOCKERFILE,
    "docker-compose.yml": DOCKER_COMPOSE,
    ".env.example": ENV_EXAMPLE,
    "README.md": README,
}


def generate_project(base_dir):
    """生成项目脚手架"""
    project_dir = os.path.join(base_dir, PROJECT_NAME)
    print(f"🏗️  生成项目脚手架:{project_dir}\n")

    created = []
    for rel_path, content in FILES.items():
        full_path = os.path.join(project_dir, rel_path)
        os.makedirs(os.path.dirname(full_path), exist_ok=True)
        with open(full_path, "w", encoding="utf-8") as f:
            f.write(content)
        created.append(rel_path)

    return project_dir, created


def print_tree(path, prefix=""):
    """打印目录树"""
    if os.path.isfile(path):
        return
    entries = sorted(os.listdir(path))
    dirs = [e for e in entries if os.path.isdir(os.path.join(path, e))]
    files = [e for e in entries if os.path.isfile(os.path.join(path, e))]
    items = [(d, True) for d in dirs] + [(f, False) for f in files]
    for i, (name, is_dir) in enumerate(items):
        is_last = (i == len(items) - 1)
        connector = "└── " if is_last else "├── "
        display = f"{name}/" if is_dir else name
        print(f"{prefix}{connector}{display}")
        if is_dir:
            ext = "    " if is_last else "│   "
            print_tree(os.path.join(path, name), prefix + ext)


def main():
    print("🏭 第13课:项目工程化 - 脚手架生成器\n")
    base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    project_dir, created = generate_project(base)

    print(f"✅ 共生成 {len(created)} 个文件\n")
    print("📂 项目结构:")
    print(f"{'─'*40}")
    print(f"{PROJECT_NAME}/")
    print_tree(project_dir)
    print(f"{'─'*40}")

    print("\n📋 生成文件清单:")
    for f in created:
        print(f"   ✓ {f}")

    print("\n🚀 下一步操作:")
    print("   1. cd maintenance-ai")
    print("   2. cp .env.example .env  (填入API Key)")
    print("   3. pip install -r requirements.txt")
    print("   4. python -m src.main")
    print("   5. 打开 http://localhost:8000/docs 查看API文档")


if __name__ == "__main__":
    main()

内容概要:本文档详细介绍了基于非线性反步法Lyapunov函数相结合的模型预测控制(Lyapunov-MPC)在自主水下航行器(AUV)轨迹跟踪中的应用,涵盖经典的Fossen六自由度动力学建模。研究通过融合反步法的系统化递推设计优势MPC的滚动优化及约束处理能力,构建了一种高性能、强鲁棒性的复合控制策略,有效提升了AUV在复杂海洋环境下的轨迹跟踪精度系统稳定性。文档提供了完整的Matlab代码实现方案,适用于高水平学术论文(如SCI一区)的复现科研验证,具有较强的理论深度工程实践价值。; 适合人群:具备自动控制理论、非线性系统分析、现代控制方法(如反步法、李雅普诺夫稳定性理论、MPC)基础,并熟悉Matlab/Simulink仿真工具的研究生、科研人员及从事水下机器人、无人系统控制开发的工程技术人员。; 使用场景及目标:①用于高精度AUV轨迹跟踪控制系统的设计仿真验证;②深入学习和掌握非线性反步法的设计流程、Lyapunov稳定性分析方法及其MPC框架的集成技巧;③服务于高水平学术论文的复现、算法对比技术创新研究,推动水下航行器智能控制技术的发展。; 阅读建议:建议读者首先深入理解Fossen动力学模型的物理意义数学表达,重点剖析反步法的虚拟控制量构造李雅普诺夫函数的设计思路,进而研究如何将稳定性条件融入MPC的优化目标中。务必结合所提供的Matlab代码进行逐行调试参数敏感性分析,通过仿真实验直观感受不同海况初始偏差下的控制性能,从而深刻理解理论设计实际效果之间的内在联系。
源码链接: https://pan.quark.cn/s/8f33d1350bc1 在电子工程领域中,选择理解芯片扮演着关键角色。当我们面对陌生的芯片时,检索相关文献是获取必要信息的主要途径。以下是一些推荐的芯片资料检索平台,它们能够协助工程师们迅速获取所需数据,从而提升设计工作的效率。 1. **329 万 PDF 集成芯片资料下载**(http://www.sylxb.cn/PDF/pdfsearch.html):该网站汇集了众多PDF格式的芯片数据手册,支持用户在线查阅或下载,是搜集芯片规格和参数的优选资源。 2. **Datasheet search 集成电路速查网**:作为一个专门的集成电路检索平台,该网站通过关键词搜索可迅速定位芯片的技术参数和应用指南。 3. **21icsearch 芯片查询网**(http://www.21icsearch.com):21icsearch 是中国领先的电子技术网站,其丰富的芯片数据库不仅包含详尽的芯片资料,还设有相关论坛和社区供工程师们交流探讨。 4. **datasheetpdf 芯片查询网**:此网站专注于提供PDF格式的芯片数据手册,便于用户快速获取和查阅芯片的详细规格。 5. **IC112 芯片查询网**:IC112 提供了大量的芯片资料,涵盖引脚布局、功能说明、电气特性等,对于设计人员而言极具实用价值。 6. **中国电子市场网**(www.dzsc.com):除了芯片资料查询功能,该网站还支持在线购买和交易,是电子元件采购的重要渠道。 7. **中国最大的芯片交易网**(www.ic72.com):该网站不仅提供芯片查询服务,还实时更新市场价格动态,对于关注市场变化的设计师具有重要参考意义。 ...
内容概要:本文围绕高维多阶段随机规划问题展开研究,重点探讨了正则化分解方法马尔可夫不确定性建模的结合应用,旨在解决大规模复杂系统中因维度高、阶段多及不确定性因素强导致的求解难题。通过构建具有马尔可夫特性的随机过程模型,刻画系统状态转移规律,并引入正则化手段提升分解算法的收敛性稳定性,有效降低计算复杂度。文中提供了完整的Python代码实现,涵盖问题建模、场景生成、算法设计数值仿真全过程,便于读者复现并应用于能源系统规划、电力调度、综合能源管理等实际场景。; 适合人群:具备一定优化理论基础和Python编程能力的研究生、科研人员及从事运筹优化、能源系统分析等相关领域的工程技术人员,尤其适合致力于复杂决策系统建模求解的研究者。; 使用场景及目标:①掌握高维随机规划问题的建模思路求解框架;②理解正则化分解在多阶段决策中的加速收敛机制;③学习如何将马尔可夫链融入不确定性建模以提升策略鲁棒性;④应用于风光储协同调度、氢能系统优化、微电网运行等实际工程问题中。; 阅读建议:建议结合文中提供的Python代码逐模块分析,重点关注状态空间离散化、场景树构造、近似动态规划流程及正则项设计技巧,同时可拓展至分布鲁棒优化、数据驱动建模等前沿方向进行深化研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值