Django集成AI落地指南:从API调用到pgvector语义检索 实际做 Django 项目时AI 能力落地往往不是“装一个库就能跑通”那么简单。社区里讨论最多的问题集中在现有 Django 项目应该直接请求大模型 API还是自己部署开源模型向量检索该用独立数据库还是直接复用 PostgreSQL模型返回结果不稳定时业务代码该在哪里兜底。这些问题的公共交集就是 Django、AI 与开源这三件事如何组合在一起。在 Django 社区Paolo Melchiorre 是长期关注开源生态和 PostgreSQL 技术的资深开发者他近年分享中的一条主线是AI 功能不应该被做成一个脱离业务系统的黑盒而应该借助 Python 开源生态把它自然地嵌入 Django 的视图、ORM 和任务队列里。这篇文章围绕这条主线展开先讲清 Django 在 AI 时代的定位再给出可运行的最小项目、语义检索案例、验证方法和生产实践建议。1. Django、AI 与开源这个主题为什么值得展开1.1 Django 在 AI 应用里的真实位置很多人一提到 AI 应用开发第一反应是 FastAPI理由是异步性能和轻量。这个判断在纯 API 服务里有道理但在完整业务系统里并不总是成立。真实项目往往已经有用户体系、权限、后台管理、数据库迁移和定时任务这些能力 Django 开箱即用FastAPI 则需要自己拼装。所以更合理的分工是需要快速迭代、复杂业务建模和成熟后台的 Web 系统继续用 Django模型推理、向量检索等计算密集部分可以作为独立服务或 Django 内的一个模块接入。Paolo Melchiorre 在多次技术分享中强调的正是这种“复用已有 Web 框架而不是推翻重来”的思路这也是开源社区里 Django 与 AI 结合的主流路径。1.2 开源生态决定了 Django 集成 AI 的方式Django 集成 AI 的便利性更多来自 Python 开源生态而不是 Django 框架本身。PyTorch、Transformers、LangChain、OpenAI SDK、pgvector 都是独立项目但因为都基于 PythonDjango 可以很自然地调用它们。这种组合关系是开源的典型优势每个组件只负责一件事通过稳定接口拼接。实际项目中常见的技术组合如下能力开源组件在 Django 中的位置Web 框架Django请求入口、业务编排、后台管理模型推理PyTorch / Transformers独立服务或被视图调用的模块大模型 API 访问openai 等 SDKservice 层封装向量存储pgvectorPostgreSQL 扩展配合 ORM任务处理Celery / Django Q异步生成摘要、向量化等耗时任务配置管理django-environ / pydantic-settings读取 Key、模型名等参数选择这条路线的直接收益是不需要为 AI 功能引入一套完全不同的技术栈团队已有的 Django 经验仍然有效。1.3 从 Paolo Melchiorre 的分享中能提炼出的开发思路Paolo Melchiorre 是 Django 社区的活跃成员也是 Django 软件基金会成员长期关注 PostgreSQL、性能和开源协作。他近年分享的 AI 相关内容有一个共同点不把 AI 当作魔法而是当作一种需要工程化管理的依赖。比如用 PostgreSQL 的 pgvector 做语义检索时他更关注索引、迁移和查询性能而不是模型本身多聪明。这种思路对普通开发者很有参考价值。接入 AI 能力时最容易犯的错误是只关心模型效果忽略工程链路接口超时怎么办Key 泄露怎么办向量数据如何迁移模型返回 JSON 不稳定如何解析。后面几个问题才是 Django 项目里真正需要花时间处理的。这篇文章的实操案例也会按这个顺序展开先讲配置和最小调用再讲向量检索最后讲生产环境需要注意的工程细节。2. 环境准备先对齐 Python、Django 和数据库版本2.1 版本选择和依赖清单在开始写代码之前先梳理依赖。不同版本的 Django 对 Python 版本有要求psycopg 和 pgvector 的安装方式也不一样版本不匹配是最常见的起步坑。以一套相对稳定的组合为例Python 3.11 或 3.12Django 4.2 LTSPostgreSQL 15 或以上并安装 pgvector 扩展psycopg 3openai 3.x 或兼容的 SDK 版本django-environ对应requirements.txt可以写成Django4.2,5.0 psycopg[binary]3.1 openai1.0 pgvector0.2 django-environ0.11 requests2.31这里把requests也列进来是因为不是所有 AI 服务都提供官方 SDK有些场景用普通 HTTP 请求更可控。如果项目只需要调用 OpenAI 兼容接口requests可以省掉。注意如果原始项目没有锁定版本落地前要先确认 Django 版本、Python 版本和 PostgreSQL 大版本。Django 4.2 是目前稳定性较好的 LTS 版本但新项目也可以评估最新版本重点是 README 和 CI 里明确版本范围避免不同开发者本地环境不一致。2.2 创建 Django 项目和应用的命令序列假设从零开始按下面的命令创建项目结构python -m venv .venv source .venv/bin/activate pip install -r requirements.txt django-admin startproject aiproject . python manage.py startapp aichat python manage.py startapp searchapp创建后目录结构大致如下. ├── aiproject │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── aichat │ ├── models.py │ ├── views.py │ └── services.py ├── searchapp │ ├── models.py │ └── views.py ├── manage.py └── requirements.txt把aichat和searchapp注册到INSTALLED_APPS里再配置数据库连接。使用 PostgreSQL 时settings.py里要写import environ env environ.Env() environ.Env.read_env() DATABASES { default: { ENGINE: django.db.backends.postgresql, NAME: env(DB_NAME, defaultaiproject), USER: env(DB_USER, defaultpostgres), PASSWORD: env(DB_PASSWORD, defaultpostgres), HOST: env(DB_HOST, default127.0.0.1), PORT: env(DB_PORT, default5432), } }用django-environ而不是在代码里硬编码密码是为了防止 Key 和数据库口令进版本库。.env文件要加入.gitignore。2.3 环境检查清单配置完环境后不要急着写业务代码先跑一遍检查运行python manage.py check确认 Django 配置没有语法错误。运行python manage.py migrate确认数据库连接正常迁移表能创建。运行python -c import pgvector; print(pgvector.__version__)确认向量扩展库可导入。在 PostgreSQL 里执行CREATE EXTENSION IF NOT EXISTS vector;确认数据库扩展权限可用。这个清单虽然简单但能过滤掉至少一半的“代码没错但跑不起来”的情况。数据库扩展权限尤其容易被忽略很多云数据库实例不允许用户手动创建扩展需要提前在控制台开启。3. 最小可运行案例在 Django 里调用大模型接口3.1 把 API Key 和模型参数放进配置AI 接口调用最忌讳把密钥写在视图里。推荐做法是统一放到环境变量再用settings.py读取。在.env文件中OPENAI_API_KEYsk-xxxx OPENAI_BASE_URLhttps://api.openai.com/v1 OPENAI_MODELgpt-4o-mini然后在settings.py中追加OPENAI_API_KEY env(OPENAI_API_KEY, default) OPENAI_BASE_URL env(OPENAI_BASE_URL, defaulthttps://api.openai.com/v1) OPENAI_MODEL env(OPENAI_MODEL, defaultgpt-4o-mini)这里使用default是为了开发环境方便但生产环境必须在部署平台配置真实值并且启动脚本要检查非空。留空的 Key 如果被使用SDK 会抛出认证异常这个异常应该被记录并返回给调用方而不是在视图里裸奔。3.2 实现 AI 服务模块在aichat/services.py中封装一个最小调用函数import json import logging from django.conf import settings import requests logger logging.getLogger(__name__) def chat_completion(system_prompt: str, user_message: str, temperature: float 0.7) - str: if not settings.OPENAI_API_KEY: raise ValueError(OPENAI_API_KEY is not configured) url f{settings.OPENAI_BASE_URL.rstrip(/)}/chat/completions headers { Authorization: fBearer {settings.OPENAI_API_KEY}, Content-Type: application/json, } payload { model: settings.OPENAI_MODEL, messages: [ {role: system, content: system_prompt}, {role: user, content: user_message}, ], temperature: temperature, } response requests.post(url, headersheaders, jsonpayload, timeout30) response.raise_for_status() data response.json() content data[choices][0][message][content] return content这段代码有几个关键点需要说明。第一使用requests而不是直接依赖特定 SDK好处是方便对接兼容 OpenAI 协议的服务包括本地部署的开源模型网关。第二timeout30是必须的。大模型接口响应不稳定没有超时可能导致 Django 进程被大量占用。第三raise_for_status()会把 HTTP 错误变成异常由上层统一处理不吞错。3.3 通过视图暴露对话接口接着写一个简单的视图函数接收用户输入并返回模型结果import json from django.http import JsonResponse from django.views.decorators.http import require_POST from .services import chat_completion require_POST def chat_view(request): try: payload json.loads(request.body) user_message payload.get(message, ) except json.JSONDecodeError: return JsonResponse({error: invalid json}, status400) if not user_message.strip(): return JsonResponse({error: message is required}, status400) try: reply chat_completion( system_promptYou are a helpful Django assistant., user_messageuser_message, ) except Exception as exc: return JsonResponse( {error: ai service error, detail: str(exc)}, status502, ) return JsonResponse({reply: reply})在urls.py里注册from django.urls import path from aichat.views import chat_view urlpatterns [ path(api/chat, chat_view, namechat), ]注意视图只做三件事解析输入、调用服务、返回统一格式。业务校验放在服务层或表单层视图层不写大量 AI 逻辑后续替换模型服务时只需要改services.py。4. 进阶案例用 pgvector 在 Django ORM 里做语义检索4.1 为什么选择 pgvector而不是单独部署向量库语义检索是 AI 应用里最常见的能力比如知识库问答、文档推荐、相似标题匹配。实现方案通常有两种单独部署 Milvus、Qdrant 或 Weaviate或者使用 PostgreSQL 的 pgvector 扩展。单独向量数据库适合数据量极大、检索 QPS 极高的场景但工程复杂度也明显更高需要维护第二个存储系统处理数据同步和跨库事务。对于大多数 Django 项目文档量在几万到几十万级别pgvector 已经足够而且能和业务数据放在同一个数据库里直接用 ORM 写查询事务和备份策略也统一。Paolo Melchiorre 在分享中偏好的正是这种“数据库内向量”方案。4.2 模型和迁移怎么写先确认 PostgreSQL 中已经执行过CREATE EXTENSION IF NOT EXISTS vector;然后在searchapp/models.py中定义文档模型from django.db import models from pgvector.django import VectorField class Document(models.Model): title models.CharField(max_length255) content models.TextField() embedding VectorField(dimensions1536, nullTrue, blankTrue) created_at models.DateTimeField(auto_now_addTrue) class Meta: indexes [ models.Index( namedocument_embedding_idx, fields[id], opclasses[halfvec_cosine_ops], ) ]这里的dimensions1536对应 OpenAItext-embedding-3-small等模型输出的向量维度。如果使用其他嵌入模型维度必须同步修改否则插入数据时会报错。索引部分要特别说明。pgvector 支持 HNSW 和 IVFFlat 两种索引opclasses里的halfvec_cosine_ops表示使用余弦相似度。创建索引的迁移最好单独写因为数据量大时耗时较长。生成迁移并执行python manage.py makemigrations searchapp python manage.py migrate4.3 写入向量和执行相似度查询生成嵌入向量通常要调用嵌入模型接口封装成服务函数import requests from django.conf import settings def generate_embedding(text: str) - list[float]: if not settings.OPENAI_API_KEY: raise ValueError(OPENAI_API_KEY is not configured) url f{settings.OPENAI_BASE_URL.rstrip(/)}/embeddings headers { Authorization: fBearer {settings.OPENAI_API_KEY}, Content-Type: application/json, } payload { model: settings.OPENAI_EMBEDDING_MODEL, input: text, } response requests.post(url, headersheaders, jsonpayload, timeout30) response.raise_for_status() return response.json()[data][0][embedding]写入文档时同时保存向量from searchapp.models import Document from searchapp.services import generate_embedding doc Document.objects.create( titleDjango 与 pgvector, content使用 PostgreSQL 扩展来存储和检索向量数据。, embeddinggenerate_embedding(Django 与 pgvector), )查询相似文档时使用CosineDistance或L2Distancefrom django.contrib.postgres.search import TrigramSimilarity from pgvector.django import CosineDistance query_embedding generate_embedding(如何做向量检索) results ( Document.objects .exclude(embedding__isnullTrue) .annotate(distanceCosineDistance(embedding, query_embedding)) .order_by(distance)[:5] ) for doc in results: print(doc.title, doc.distance)CosineDistance返回的是余弦距离数值越小表示越相似。用[:5]做 Top-K 截断避免把大量不相关结果返回给用户。5. 运行验证从启动项目到检查返回结果5.1 启动服务并确认基础页面运行开发服务器python manage.py runserver 127.0.0.1:8000浏览器访问http://127.0.0.1:8000/api/chat如果没有 GET 接口会看到 405 响应这是正常的说明 URL 注册成功。再访问http://127.0.0.1:8000/admin确认后台页面正常。5.2 用 curl 验证对话接口使用curl模拟 POST 请求curl -X POST http://127.0.0.1:8000/api/chat \ -H Content-Type: application/json \ -d {message: 用一句话解释 Django 的 ORM}正常返回{ reply: Django 的 ORM 是一种将 Python 类和数据库表映射起来的对象关系映射机制开发者可以直接用 Python 代码操作数据库。 }如果返回{error: ai service error, detail: ...}把 detail 中的错误信息与第 6 节的排查表对照。5.3 验证向量检索的预期输出先插入几条测试文档python manage.py shell -c from searchapp.models import Document from searchapp.services import generate_embedding Document.objects.create( titleHTTP 缓存, content通过 Cache-Control 响应头控制浏览器缓存行为。, embeddinggenerate_embedding(HTTP 缓存), ) 然后执行相似查询确认与查询语义相近的文档排在最前面完全不相关的文档被过滤或排在后面。这一步验证的不只是代码正确性还有分词、嵌入模型和距离计算是否整体可用。6. 常见问题排查AI 集成中最容易出错的五个环节6.1 配置类问题在实际项目里配置类错误排在第一位。问题现象常见原因检查方式处理建议接口返回 401 或 403API Key 未配置或已失效检查settings.py中 OPENAI_API_KEY 是否为空在.env中补全 Key重启服务本地正常生产环境报配置缺失.env未同步或环境变量未注入在部署平台查看环境变量列表使用部署平台的环境变量管理不要把.env提交到仓库模型名错误使用了不存在的模型标识打印settings.OPENAI_MODEL与模型服务商文档核对模型名6.2 依赖和数据库问题向量功能相关的问题集中表现为UndefinedObject: type vector does not exist说明未创建 pgvector 扩展执行CREATE EXTENSION IF NOT EXISTS vector;。type vector does not exist出现在迁移时当前数据库用户可能没有超级权限需要管理员账号创建扩展。VectorField导入失败pgvectorPython 包未安装或者 Django 版本不兼容。6.3 请求超时和并发问题大模型接口在请求高峰期可能超过默认超时时间。排查路径如下先看 Django 日志中是否有TimeoutError或ConnectionError。检查视图层的timeout参数是否设置合理建议 30 秒到 60 秒。如果接口需要长时间等待不要让 HTTP 请求同步阻塞。应改为请求进来后创建任务返回任务 ID由 Celery 后台执行 AI 调用前端轮询或通过 WebSocket 获取结果。生产环境并发量大时同步调用外部 AI 接口会快速耗尽 Gunicorn worker。推荐把 AI 请求放到任务队列通过task.apply_async异步执行这样 Django 进程只负责接收任务和返回任务状态。7. 开源选型与生产实践什么时候该自己部署模型7.1 API 调用 vs 本地部署模型开源大模型让“本地部署”成为可行选项但并不是所有项目都需要立刻部署。两者对比维度API 调用本地部署开源模型上手成本低注册即可使用高需要 GPU、推理框架、运维数据隐私数据离开自有环境数据保存在内部单次成本按 token 付费主要是硬件和电费模型迭代供应商维护需要自己跟进新版本稳定性依赖外部服务依赖内部运维能力从开源项目的角度看本地部署的优势是可控性和数据隐私但对大多数中小团队初期先用 API 跑通业务再逐步评估是否值得转入本地部署是更稳妥的路径。7.2 许可证和开源组件合规集成开源模型时许可证检查是很容易被忽略的一环。常见开源模型许可证包括 Apache 2.0、MIT、Llama 社区许可等商用限制和衍生作品条款差别很大。实际项目里建议做四件事记录每个开源组件的名称、版本和许可证。在项目 README 中声明依赖许可证。如果公司有法务或合规流程在引入新模型前提交许可证审核。不要把核心业务数据发送到条款不明确的服务。这些工作不直接影响功能但决定项目能否安全落地。7.3 生产环境必须补齐的工程能力学习环境跑通只是第一步生产环境还要考虑配置外置化所有密钥、模型名、超时时间通过环境变量或配置中心管理。日志和监控记录每个 AI 请求的耗时、token 消耗、错误码便于成本核算和故障定位。权限和限流AI 接口通常成本高需要对调用方做限流和鉴权避免被刷。异常兜底模型返回格式不稳定时添加 JSON 解析容错服务不可用时提供降级文案。回滚方案模型升级后如果效果下降要能快速切回旧版本。8. 收尾一个可落地的技术判断Django 项目接入 AI 能力时真正改变开发方式的不是模型本身而是围绕模型建立的一整套工程链路。Paolo Melchiorre 的开源和 AI 分享提供了一个重要视角不要为了 AI 重构整个系统而是把 AI 当作一个需要配置、监控和迭代的模块放入已有的 Django 工程体系。对新手来说最有价值的练习是沿着这篇文章的顺序先跑通/api/chat对话接口再动手做 pgvector 语义检索最后把同步调用改成异步任务。对已经在生产环境使用 Django 的团队来说优先要解决的是密钥管理、超时策略、日志成本和模型回滚而不是盲目更换框架。下一个可以继续深挖的方向是用 Django 的Signals或任务队列把文档写入和向量化拆开接入 OpenTelemetry 对 AI 请求做全链路追踪或者对比不同开源模型的检索效果和成本找到适合自己业务数据的那一个。