ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AI应用工程实践:从快速Demo到可演进的生产系统

AI应用工程实践:从快速Demo到可演进的生产系统 在 AI 行业讨论中经常听到一种判断AI 竞争不是短跑熬得久比起得早更重要。这个观点最初来自国内大型科技公司对自身 AI 投入节奏的回应但放到技术工程里同样适用。真正能长期跑下去的 AI 项目靠的不是发布更早、模型参数更大而是工程底座更稳模型可以换、Prompt 可以调、Agent 可以重写但服务架构、数据链路、监控体系和排错方法必须能支撑持续演进。下面从一个 AI 应用开发者的视角把“熬得久”翻译成可执行的工程实践如何选模型、搭环境、写最小可运行服务如何从单次问答演进到 Agent 工具调用如何把本地能跑的 Demo 变成生产可部署的服务以及遇到推理慢、显存溢出、输出质量下降时怎么定位。1. 先把“起得早”和“熬得久”翻译成工程语言1.1 起得早快速 Demo 带来先发优势也带来技术债开发者面对新技术时通常有两个冲动第一是尽快接入最新模型第二是快速做出一个能演示的页面。早期验证不是坏事它能帮助判断大模型是否适合业务场景也能提前暴露 Prompt 编写、成本、延迟等基础问题。但“起得早”在工程上往往意味着跳过一些长期维护必须的步骤例如依赖版本没有固定三个月后环境装不起来。Prompt 直接写在业务代码里无法灰度、无法回滚。模型接口返回结构变化时没有适配层上游全部报错。没有日志和 trace_id用户投诉时无法定位是哪一轮对话出了问题。这些技术债在 Demo 阶段不致命一旦进入日请求量不小的生产环境就会让团队疲惫不堪。所以快速 Demo 做验证没问题但要意识到它和生产系统是两种不同的工程对象。1.2 熬得久AI 项目真正的竞争力来自可观测、可回滚、可演进“熬得久”不是指慢慢开发而是指系统设计要允许长期迭代。一个能长期运行的 AI 应用通常具备三个特征可观测知道每一次请求调用了哪个模型、耗时多久、生成了多少 token、是否有异常。可回滚Prompt、模型版本、Agent 工具函数都是可切换的配置而不是写死在代码里。可演进模型从旧版本换到新版本时接口层不受影响工具调用协议保持稳定。为了更直观可以把快速 Demo 与长期系统的差异整理成一张表对比维度快速 Demo长期系统依赖管理直接 pip install 最新版固定版本锁定哈希可重复构建Prompt 位置写在业务逻辑中独立配置按版本管理支持灰度模型调用直接 SDK 调用抽象模型接入层可替换模型日志print 或临时文件结构化日志包含 trace_id并发控制单线程演示线程池或异步任务限流熔断错误处理页面报 500统一错误响应并带上请求 ID上线方式本地运行Docker 化灰度发布可回滚这张表回答了一个核心问题为什么很多团队 Demo 很惊艳但上线后问题不断。不是模型不够好而是工程化环节没有补齐。1.3 模型可以换工程底座不能塌长期主义在 AI 工程里最重要的体现是把模型当作“可替换组件”。今天性能较好的开源模型几个月后可能被新模型超越今天使用的商业模型接口可能调整价格或响应格式。如果业务代码直接绑定某个模型 SDK 的数据结构替换成本会非常高。推荐的做法是定义一个模型接入抽象层至少屏蔽两个差异接口协议差异和返回结构差异。这样后续切换模型时只需要新增一个适配器而不是改所有业务代码。后面的章节会围绕这个思路逐步搭建一套最小但可扩展的 AI 应用。注意这里的“长期”不是无限期维护旧代码而是保留快速替换模型、Prompt、工具链的能力。技术选型时优先选择接口边界清晰、社区稳定的框架。2. 环境准备与模型选型先固定变量再谈速度2.1 模型选型要回答的四个问题开始写代码前先要确定模型形态。模型选型不是“哪个强选哪个”而是要在数据隐私、成本、延迟、可控性之间做取舍。数据隐私业务数据是否允许发送到第三方模型接口若不允许就要选择本地部署的权重模型。成本商业 API 按 token 计费本地部署则需要 GPU 资源和运维成本两者的成本曲线差异很大。延迟本地小模型在专用 GPU 上首 token 延迟可控但性能受硬件限制商业 API 平均延迟不一定低但无需自己扩容。可控性本地模型可以自定义采样参数、量化、后处理也能通过私有化部署满足合规要求。可以按这个思路整理一张速查表选型维度商业模型 API本地开源权重模型数据隐私数据离开业务方需要评估合规数据本地处理更容易满足数据不出域成本模型按 token 付费初始便宜量增大后成本线性增长需要 GPU 硬件固定成本高量越大边际成本越低部署难度低注册 Key 即可调用高需要匹配 CUDA、显存、推理框架延迟优化依赖服务商容量和网络可以通过模型量化、推理框架、动态批处理优化模型升级服务商自动升级但行为可能变化自己控制版本灰度升级节奏可控这里要补充一句没有绝对优劣。很多团队会同时保留两条路线默认走商业 API 验证业务当数据合规或成本压力出现时再切本地模型。这种“双轨制”本身就是一种长期主义设计。2.2 本地部署最容易踩坑的三个环节如果决定本地部署环境问题往往比模型问题更早出现。常见的有三个Python 版本错乱。模型推理框架对 Python 版本有要求例如某些版本只支持 3.10 或 3.11直接用系统自带的 Python 很容易冲突。CUDA 和 PyTorch 版本不匹配。GPU 驱动、CUDA 版本、PyTorch 的 CUDA 版本必须形成兼容组合否则会出现CUDA error: no kernel image is available这类问题。依赖范围失控。直接pip install -r requirements.txt安装最新版可能在几个月后因为某个传递依赖升级而构建失败。解决思路是把环境当作代码一样管理。使用 Conda 创建独立环境记录 Python 版本使用 pip-tools 生成固定版本的依赖清单对于 GPU 相关依赖明确记录驱动和 CUDA 版本。不要把“刚才还能跑”作为可靠的判断依据。2.3 用 Conda 和 pip-tools 固定依赖环境下面是一组适用于学习环境的命令。以模型推理常用的 Python 3.11 为例先创建环境conda create -n ai-app python3.11 conda activate ai-app pip install pip-tools然后创建一个requirements.in文件只写顶层依赖例如fastapi uvicorn[standard] pydantic loguru requests transformers torch注意torch的安装通常需要对应 CUDA 版本。若本机已经安装了匹配的 CUDA 驱动可以使用带 CUDA 版本的安装命令例如pip install torch --index-url https://download.pytorch.org/whl/cu121这个命令只是示例。实际装什么版本要先去 PyTorch 官网确认与本机 CUDA 版本匹配的 index-url不要凭记忆写。如果网络环境受限可以配置本机构建源但核心原则不变固定版本、可复现。生成固定版本文件pip-compile requirements.in pip install -r requirements.txt这样生成的requirements.txt会包含完整依赖树及精确版本。后续每次需要升级依赖时先修改requirements.in再重新执行pip-compile。注意学习环境固定依赖看起来多此一举但等三个月后重新复现实验或部署到服务器时这一步能节省大量排查时间。2.4 如果使用云主机或 VPS还要额外确认什么如果项目最终要部署到云主机或 VPS光在本机跑通还不够。需要在部署前确认四点操作系统版本和内核是否符合推理框架要求。例如很多 GPU 推理镜像基于 Ubuntu 20.04 或 22.04。GPU 驱动是否安装完成nvidia-smi是否能正常输出。是否有独立 IP、端口是否开放以及安全组策略是否允许指定端口访问。内存和磁盘是否足够模型权重往往有几个 GB 到几十 GB。对于没有 GPU 的云主机可以选择小型模型、CPU 推理或直接使用商业 API。CPU 推理在低并发场景也能工作但首 token 延迟通常会明显高于 GPU压测时要先确认业务能否接受。3. 最小可运行的 AI 应用FastAPI 封装大模型接口3.1 项目结构设计环境准备完成后需要一个能运行的最小项目。这里选择 FastAPI原因有三个类型提示友好、自动生成 OpenAPI 文档、适合构建 HTTP 服务。项目结构可以这样组织ai-app/ ├── app/ │ ├── __init__.py │ ├── main.py # FastAPI 入口 │ ├── config.py # 配置管理 │ ├── models/ │ │ ├── __init__.py │ │ ├── local_model.py # 本地模型适配器 │ │ └── remote_model.py # 远程 API 适配器 │ ├── schemas/ │ │ ├── __init__.py │ │ ├── request.py # 请求体定义 │ │ └── response.py # 响应体定义 │ └── services/ │ ├── __init__.py │ └── generator.py # 生成逻辑 ├── prompts/ │ └── chat.yaml # Prompt 模板 ├── requirements.txt └── Dockerfile这个结构不复杂但已经划分了配置、模型接入、请求校验、业务逻辑四层。后续替换模型时只需要改models/下的适配器调整 Prompt 时不需要动 Python 代码。3.2 模型加载不要每次请求都初始化初学者最常见的错误是在每个接口函数里加载模型。加载一个几 GB 到几十 GB 的权重非常耗时会让请求全部超时。正确做法是在进程启动时加载一次并放到内存中复用。下面是一个简单的本地模型适配器示例使用 Hugging Face Transformers 加载对话模型。代码中以Qwen2.5-7B-Instruct为例实际运行前需要确认模型名称和本地路径import os from transformers import AutoTokenizer, AutoModelForCausalLM class LocalModel: def __init__(self, model_path: str): self.tokenizer AutoTokenizer.from_pretrained(model_path) self.model AutoModelForCausalLM.from_pretrained( model_path, device_mapauto, torch_dtypeauto, ) self.model.eval() def generate(self, prompt: str, max_new_tokens: int 512, temperature: float 0.7): inputs self.tokenizer(prompt, return_tensorspt) inputs {k: v.to(self.model.device) for k, v in inputs.items()} outputs self.model.generate( **inputs, max_new_tokensmax_new_tokens, temperaturetemperature, do_sampletemperature
返回列表