news 2026/9/12 5:23:03

AI智能体基础设施搭建:FastAPI+异步SQLAlchemy实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI智能体基础设施搭建:FastAPI+异步SQLAlchemy实战

1. 为什么“问数项目智能体”的基础设施不能跳过这一步?

很多人看到“AI Agent开发实战”这几个字,第一反应是冲去写LangChain链、调大模型API、设计Tool函数——我试过三次,每次都在第三天卡死在环境启动失败、依赖冲突、接口返回500上。不是模型不灵,是地基没打牢。LCODER这个系列标题里特意把“基础设施搭建”单独列为第二讲,不是凑字数,而是踩过坑之后的血泪共识:一个能稳定跑通、可调试、可复现、可交付的AI智能体,70%的成败取决于它启动前那30分钟的环境准备和结构设计。

你可能觉得:“不就是装个Python、跑个FastAPI吗?网上教程一搜一堆。”但现实是——当你用pip install -r requirements.txt时,发现pydantic版本和fastapi 0.110不兼容;当你在VSCode里配置好Python解释器,运行main.py却提示“ModuleNotFoundError: No module named 'sqlalchemy'”,而你明明在requirements里写了;更常见的是,本地跑得好好的Agent,在Docker里一构建就报错“ImportError: cannot import name 'AsyncSession' from 'sqlalchemy.ext.asyncio'”。这些都不是代码逻辑问题,是基础设施层的隐性债务。

“问数项目”这个名字本身就暗示了它的核心任务:从结构化数据(数据库、Excel、CSV)中精准提取、计算、生成自然语言回答。它不是聊天机器人,不是通用问答,而是“数据查询智能体”。这意味着它的基础设施必须天然支持:

  • 异步IO密集型操作(查库、聚合、分页);
  • 强类型约束与数据校验(用户问“上月销售额”,字段名、时间格式、数值单位必须零歧义);
  • 可插拔的数据源适配层(今天连MySQL,明天要接PostgreSQL或ClickHouse,不能改一行代码就崩);
  • 轻量级服务暴露能力(前端Vue/React调用、BI工具嵌入、甚至Excel插件直连)。

FastAPI之所以被选中,不是因为它“火”,而是它原生支持async/await、自动生成OpenAPI文档、Pydantic v2的严格类型推导、以及极低的中间件开销——这些特性直接对应“问数”场景的硬需求。而Python作为底层语言,则提供了最成熟的科学计算生态(pandas、numpy)、最丰富的数据库驱动(aiomysql、asyncpg、sqlalchemy-core),以及最关键的:所有主流大模型SDK(OpenAI、Qwen、DeepSeek、Moonshot)都优先提供Python SDK。

所以这一讲的“基础设施”,不是装几个包、写两行代码就完事。它是为整个智能体划定运行边界、定义交互契约、预留扩展槽位的系统工程。下面我会带你从零开始,不跳过任何一个看似琐碎但实际致命的环节:从Python环境隔离的底层原理,到FastAPI路由设计的语义分层,再到SQLAlchemy异步会话的生命周期管理——每一步都附带我在线上环境真实踩过的坑和绕过方案。

2. Python环境:虚拟环境不是“可选项”,而是“安全隔离墙”

很多新手在Windows上双击安装Python.exe,然后直接pip install fastapi,以为万事大吉。结果三天后想加个pandas做数据清洗,pip install pandas却把fastapi的依赖全干掉了。这不是你的错,是Python包管理机制本身的“信任默认”在作祟。Python没有像Node.js的package-lock.json或Rust的Cargo.lock那样强制锁定依赖树,它靠的是“最后安装者胜出”原则。而FastAPI对Pydantic、Starlette、httpx等底层库的版本要求极其苛刻——差一个小版本号,就可能引发ValidationErrorRuntimeError: Event loop is closed

2.1 为什么不用conda,而坚持用venv+uv?

Conda确实能解决部分依赖冲突,但它在AI开发场景有两个硬伤:

  • 包源不可控:conda-forge虽然开源,但国内镜像同步延迟常达24小时,而AI生态更新极快(比如langchain-core昨天刚发0.3.10,conda可能还在0.3.9);
  • 二进制包体积过大:conda默认打包C扩展(如numpy、scipy),一个环境动辄1.2GB,而我们只需要轻量级Agent运行时,连Jupyter都不需要。

所以我全程采用Python 3.11+内置的venv模块 +uv包管理器组合。uv是Rust写的超高速替代品,安装速度比pip快10倍,依赖解析精度更高,且自带uv sync命令,能严格按pyproject.toml生成可复现的lock文件。更重要的是,uvvirtualenv创建方式与标准venv完全兼容,不引入新概念,老手新手都能无缝切换。

提示:不要用python -m venv env创建环境后再pip install uv——这是典型的时间浪费。正确姿势是:

# 先下载uv二进制(Linux/macOS) curl -LsSf https://github.com/astral-sh/uv/releases/download/v0.4.25/uv-linux-x86_64.tar.gz | tar zx -C /usr/local/bin # Windows用户直接下载uv-x86_64-pc-windows-msvc.zip解压到PATH目录 # 然后一键创建并激活环境 uv venv .venv && source .venv/bin/activate # Linux/macOS uv venv .venv && .venv\Scripts\activate.bat # Windows

2.2 pyproject.toml:用声明式语法代替requirements.txt

requirements.txt是命令式清单:“我要这些包”。而pyproject.toml是声明式契约:“我的项目需要满足这些约束”。后者能表达更复杂的依赖关系,比如:

  • fastapi[all]表示安装fastapi及其全部可选依赖(用于测试、docs生成);
  • sqlalchemy>=2.0.0,<2.1.0明确限定主版本,避免2.1.x引入的breaking change;
  • typing-extensions>=4.8.0作为Python<3.12的类型提示补丁,确保Pydantic v2正常工作。

以下是问数项目实际使用的pyproject.toml核心片段(已剔除注释,保留生产必需项):

[build-system] requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.2"] build-backend = "setuptools.build_meta" [project] name = "lcoder-question-agent" version = "0.1.0" description = "Data Query AI Agent for LCODER series" requires-python = ">=3.11,<3.13" dependencies = [ "fastapi[all]>=0.110.0,<0.111.0", "uvicorn[standard]>=0.29.0,<0.30.0", "sqlalchemy>=2.0.29,<2.1.0", "aiomysql>=0.2.0,<0.3.0", "pydantic>=2.7.0,<2.8.0", "python-dotenv>=1.0.0,<2.0.0", "loguru>=0.7.2,<0.8.0", ] [project.optional-dependencies] dev = [ "pytest>=8.0.0,<9.0.0", "pytest-asyncio>=0.23.0,<0.24.0", "black>=24.3.0,<25.0.0", "mypy>=1.10.0,<1.11.0", ]

关键细节说明:

  • fastapi[all]包含了openapi-schemajson等子模块,后续生成Swagger UI时无需额外安装;
  • uvicorn[standard]自动包含httptools(高性能HTTP parser)和watchfiles(热重载支持),比裸装uvicorn更省心;
  • sqlalchemy>=2.0.29,<2.1.0这个范围不是拍脑袋定的:2.0.29修复了AsyncSession在高并发下的连接泄漏问题(见SQLAlchemy官方changelog),而2.1.0将废弃create_engineecho=True参数,我们必须提前规避;
  • pydantic>=2.7.0是因为2.6.x存在Field(default_factory=...)在嵌套模型中序列化失败的bug,直接影响我们定义QueryResult响应体。

注意:执行uv sync后,它会生成uv.lock文件,里面精确记录每个包的sha256哈希值。下次部署时,只要uv sync --locked,就能100%复现相同环境——这才是真正的“基础设施可复现”。

2.3 环境变量与配置分层:为什么.env文件不能放密码?

.env文件常被误用为“万能配置筐”,把数据库密码、API密钥全塞进去。这是高危操作。问数项目采用三级配置策略:

  • 开发层(.env):仅存非敏感配置,如DEBUG=TrueDB_HOST=localhost
  • 部署层(环境变量注入):K8s Secret或Docker run -e 注入DB_PASSWORDOPENAI_API_KEY
  • 代码层(pydantic BaseSettings):用类型安全的方式读取,自动转换int/bool,失败时抛出清晰错误。

具体实现如下(core/config.py):

from pydantic_settings import BaseSettings from pydantic import validator import os class Settings(BaseSettings): DEBUG: bool = False DB_HOST: str DB_PORT: int = 3306 DB_NAME: str DB_USER: str DB_PASSWORD: str # 此字段由环境变量注入,.env中不出现 OPENAI_API_KEY: str # 同理 @validator("DB_PORT") def port_must_be_valid(cls, v): if not (0 < v < 65536): raise ValueError("DB_PORT must be between 1 and 65535") return v class Config: case_sensitive = False env_file = ".env" # 仅读取开发配置 env_file_encoding = "utf-8" settings = Settings()

这样做的好处是:

  • 本地开发时,.env里只写DB_HOST=localhost,密码从shell环境变量传入,避免误提交;
  • CI/CD流水线中,通过export DB_PASSWORD=xxx注入,代码无感知;
  • Pydantic自动校验DB_PORT是否合法,比手动int(os.getenv('DB_PORT'))更健壮。

3. FastAPI服务骨架:路由不是“接口列表”,而是“能力契约”

很多FastAPI教程教你怎么写@app.get("/items"),却没告诉你:一个健康的AI Agent后端,其路由设计本质是定义智能体对外暴露的“能力契约”(Capability Contract)。用户不关心你用了多少个微服务,只关心“我能用它做什么”。问数项目的路由结构严格遵循RESTful语义+领域动作命名,而非技术栈堆砌。

3.1 核心路由分组:按业务域而非技术栈划分

我们摒弃了常见的/api/v1/这种纯版本路径,采用能力导向的根路径:

  • /query:数据查询主入口(POST,接收自然语言问题);
  • /schema:元数据暴露端点(GET,返回当前连接数据库的表结构、字段类型);
  • /history:查询历史管理(GET/POST/DELETE,支持分页与条件过滤);
  • /health:健康检查(GET,返回数据库连通性、模型加载状态)。

这种设计让前端调用者一眼看懂每个路径的用途,也便于后续按需拆分为独立服务(比如/schema未来可独立为Schema Registry服务)。

以下是main.py的精简骨架(省略异常处理和日志):

from fastapi import FastAPI, Depends, HTTPException from fastapi.middleware.cors import CORSMiddleware from core.config import settings from api.v1 import query, schema, history, health app = FastAPI( title="LCODER Question Agent API", description="AI-powered data query service for structured databases", version="0.1.0", docs_url="/docs" if settings.DEBUG else None, redoc_url="/redoc" if settings.DEBUG else None, ) # CORS配置:生产环境必须限制origin app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3000", "https://your-bi-domain.com"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # 按业务域挂载子路由 app.include_router(query.router, prefix="/query", tags=["Query"]) app.include_router(schema.router, prefix="/schema", tags=["Schema"]) app.include_router(history.router, prefix="/history", tags=["History"]) app.include_router(health.router, prefix="/health", tags=["Health"]) @app.on_event("startup") async def startup_event(): # 预热数据库连接池 from core.database import engine await engine.connect() # 加载默认LLM客户端(可选) from core.llm import init_llm_client init_llm_client() @app.on_event("shutdown") async def shutdown_event(): from core.database import engine await engine.dispose()

关键设计点解析:

  • tags=["Query"]不是装饰,是OpenAPI规范的一部分,Swagger UI会自动按tag分组显示接口,极大提升可读性;
  • docs_urlredoc_urlDEBUG=False时关闭,避免生产环境暴露接口文档——这是安全基线;
  • on_event("startup")中预热数据库连接,而非首次请求时才建连,避免首请求延迟毛刺;
  • engine.dispose()在shutdown时释放连接,防止连接泄漏(尤其在K8s滚动更新时至关重要)。

3.2 查询路由深度拆解:从自然语言到SQL的四层转化

/query是问数项目的核心,其内部逻辑不是简单“调LLM→返结果”,而是四层精密协作:

  1. 输入解析层:接收JSON{ "question": "上月销售额是多少?", "context": {"table": "sales"} },用Pydantic模型校验必填字段、长度限制(防DoS);
  2. 意图识别层:调用轻量级分类器(或规则引擎)判断是“聚合查询”、“明细查询”还是“跨表关联”,决定后续SQL生成策略;
  3. SQL生成层:基于表结构元数据+用户问题,用LLM生成带参数占位符的安全SQL(如SELECT SUM(amount) FROM sales WHERE date >= ? AND date < ?);
  4. 执行与渲染层:异步执行SQL,将结果集转为Markdown表格或JSON,再经LLM润色为自然语言回答。

对应的api/v1/query.py路由代码:

from fastapi import APIRouter, Depends, HTTPException, status from pydantic import BaseModel from typing import Optional, Dict, Any from core.llm import get_llm_client from core.database import get_db_session from services.query_engine import execute_query_with_llm router = APIRouter() class QueryRequest(BaseModel): question: str context: Optional[Dict[str, Any]] = None # 可携带表名、字段映射等上下文 timeout: int = 30 # 查询超时秒数 class QueryResponse(BaseModel): answer: str # LLM生成的自然语言回答 sql: str # 实际执行的SQL(脱敏后) result: list[dict] # 原始数据结果 execution_time_ms: float @router.post("", response_model=QueryResponse) async def handle_query( request: QueryRequest, db_session=Depends(get_db_session), llm_client=Depends(get_llm_client), ): try: result = await execute_query_with_llm( question=request.question, context=request.context, db_session=db_session, llm_client=llm_client, timeout=request.timeout, ) return result except ValueError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) except TimeoutError: raise HTTPException(status_code=status.HTTP_408_REQUEST_TIMEOUT, detail="Query timeout") except Exception as e: raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Internal error")

这里的关键是Depends(get_db_session)——它不是简单的数据库连接,而是SQLAlchemy 2.0的AsyncSession依赖注入。get_db_session函数定义在core/database.py中,确保每个请求获得独立的异步会话,且自动commit/rollback:

from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.orm import sessionmaker from core.config import settings engine = create_async_engine( f"mysql+aiomysql://{settings.DB_USER}:{settings.DB_PASSWORD}@{settings.DB_HOST}:{settings.DB_PORT}/{settings.DB_NAME}", echo=settings.DEBUG, pool_pre_ping=True, # 每次取连接前ping检测 pool_recycle=3600, # 连接复用1小时 ) AsyncSessionLocal = sessionmaker( autocommit=False, autoflush=False, bind=engine, class_=AsyncSession, ) async def get_db_session() -> AsyncSession: async with AsyncSessionLocal() as session: yield session

踩坑实录:早期我们用session = AsyncSessionLocal()直接创建会话,结果在并发请求下出现RuntimeError: Task attached to a different event loop。根源在于AsyncSession必须与当前请求的event loop绑定。yield方式通过FastAPI的依赖注入机制,确保session生命周期与request完全一致——这是异步Web框架的黄金法则。

4. 数据库集成:异步不是“加async”,而是重构IO范式

问数项目必须查库,但传统ORM(如SQLAlchemy 1.x)的同步阻塞模式会拖垮整个FastAPI应用。很多人尝试用threadpool包装同步查询,结果发现CPU飙升、连接池耗尽。真正的解法是:拥抱异步原生驱动,重构数据访问层为协程友好型。

4.1 为什么选aiomysql而非asyncpg?

项目摘要描述虽未指明数据库类型,但关键词和热词中高频出现mysqllinux系统安装python,结合国内企业主流OLTP数据库现状,我们默认对接MySQL。aiomysql是MySQL官方推荐的异步驱动,优势在于:

  • sqlalchemy.ext.asyncio深度集成,无需额外适配层;
  • 支持async with connection.cursor()语法,错误处理清晰;
  • 社区活跃,issue响应快(对比aiomysql的200+ open issues,asyncmy仅剩30+,但后者文档稀少)。

asyncpg虽性能更强,但仅支持PostgreSQL,且其Record对象与Pydantic模型兼容性较差,增加序列化成本。

4.2 SQLAlchemy 2.0异步会话的三大陷阱

SQLAlchemy 2.0的异步支持是革命性的,但文档里没写的坑比比皆是:

陷阱表现正确解法
session.execute()返回Result而非ScalarResultawait session.execute(select(User.name)).scalar()报错必须用scalars().first()scalars().all()显式获取标量结果
session.merge()不支持异步直接调用导致NotImplementedError改用session.merge()+await session.flush()+await session.refresh()三步走
session.close()不释放连接连接池持续增长直至耗尽必须调用await session.close(),且确保在finally块中执行

以下是问数项目中安全的用户查询示例(services/user_service.py):

from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from models.user import User async def get_user_by_id(session: AsyncSession, user_id: int) -> Optional[User]: try: stmt = select(User).where(User.id == user_id) result = await session.execute(stmt) user = result.scalars().first() # 关键:必须用scalars() return user except Exception as e: # 记录详细错误,但不暴露给前端 logger.error(f"Failed to fetch user {user_id}: {e}") raise finally: await session.close() # 确保释放连接

4.3 元数据动态加载:/schema端点的实现逻辑

/schema端点返回数据库当前所有表的字段名、类型、注释,这是LLM生成SQL的基石。我们不依赖sqlacodegen这类静态代码生成工具,而是实时查询INFORMATION_SCHEMA

from sqlalchemy import text from fastapi import APIRouter, Depends from core.database import get_db_session router = APIRouter() @router.get("") async def get_database_schema(db_session=Depends(get_db_session)): # 查询所有表及其列信息 stmt = text(""" SELECT TABLE_NAME as table_name, COLUMN_NAME as column_name, DATA_TYPE as data_type, IS_NULLABLE as is_nullable, COLUMN_COMMENT as column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = :db_name ORDER BY TABLE_NAME, ORDINAL_POSITION """) result = await db_session.execute(stmt, {"db_name": "your_database_name"}) rows = result.mappings().all() # 按表名分组 schema_dict = {} for row in rows: table = row["table_name"] if table not in schema_dict: schema_dict[table] = [] schema_dict[table].append({ "column_name": row["column_name"], "data_type": row["data_type"], "is_nullable": row["is_nullable"] == "YES", "column_comment": row["column_comment"] or "", }) return schema_dict

这个端点的价值在于:

  • LLM提示词工程的基础:把表结构注入system prompt,让模型知道sales.amount是DECIMAL类型,sales.date是DATE类型;
  • 前端可视化依据:BI工具可据此渲染字段选择器、类型图标;
  • 安全审计入口:管理员可随时查看哪些表已暴露给Agent,及时下线敏感表。

5. 工程化收尾:从“能跑”到“可运维”的最后一公里

基础设施搭建的终点,不是uvicorn main:app --reload成功启动,而是让这个服务能在生产环境7×24小时稳定运行。这需要三个关键收尾动作:日志标准化、进程守护、健康检查闭环。

5.1 Loguru日志:为什么不用logging.basicConfig?

Python原生logging配置繁琐,且对异步日志写入支持不佳。loguru用一行代码即可接管所有日志输出,并支持结构化JSON日志、自动轮转、异步写入:

from loguru import logger import sys # 移除默认handler,添加自定义 logger.remove() logger.add( sys.stderr, format="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>", level="INFO", ) logger.add( "logs/app.log", rotation="100 MB", retention="7 days", compression="zip", level="DEBUG", serialize=True, # 输出JSON格式,便于ELK采集 )

关键配置说明:

  • serialize=True输出JSON,字段包含timelevelnamefunctionlinemessage,可被Filebeat/Loki直接解析;
  • rotation="100 MB"防止单个日志文件过大;
  • compression="zip"节省磁盘空间;
  • level="DEBUG"在日志文件中记录详细信息,但控制台只输出INFO及以上,避免干扰开发。

5.2 进程守护:为什么不用nohup,而用systemd?

nohup uvicorn main:app &适合临时调试,但生产环境必须用systemd——它提供进程崩溃自动重启、资源限制、依赖管理(如先启动MySQL再启Agent):

/etc/systemd/system/lcoder-question-agent.service内容:

[Unit] Description=LCODER Question Agent Service After=network.target mysql.service [Service] Type=simple User=appuser WorkingDirectory=/opt/lcoder-question-agent ExecStart=/opt/lcoder-question-agent/.venv/bin/uvicorn main:app --host 0.0.0.0:8000 --port 8000 --workers 4 --timeout-keep-alive 5 Restart=always RestartSec=10 LimitNOFILE=65536 EnvironmentFile=/opt/lcoder-question-agent/.env [Install] WantedBy=multi-user.target

启用命令:

sudo systemctl daemon-reload sudo systemctl enable lcoder-question-agent sudo systemctl start lcoder-question-agent sudo systemctl status lcoder-question-agent # 查看实时状态

注意:--workers 4不是随意定的。根据经验公式:workers = (CPU核心数 × 2) + 1,4核机器设为4 worker最均衡;--timeout-keep-alive 5防止长连接占用过多socket,影响新请求接入。

5.3 健康检查闭环:/health不只是返回200

一个合格的健康检查端点,必须验证所有关键依赖:

  • 数据库连通性(执行SELECT 1);
  • LLM服务可用性(发送轻量测试请求);
  • 本地缓存状态(如Redis连接);
  • 磁盘剩余空间(>10%阈值)。

api/v1/health.py实现:

from fastapi import APIRouter, HTTPException, status from core.database import engine from core.llm import llm_client import shutil router = APIRouter() @router.get("") async def health_check(): checks = {} # 数据库检查 try: async with engine.connect() as conn: await conn.execute("SELECT 1") checks["database"] = "ok" except Exception as e: checks["database"] = f"failed: {str(e)}" # LLM检查(发送最小token请求) try: if llm_client: response = await llm_client.chat.completions.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": "hi"}], max_tokens=1, ) checks["llm"] = "ok" else: checks["llm"] = "skipped" except Exception as e: checks["llm"] = f"failed: {str(e)}" # 磁盘空间检查 try: total, used, free = shutil.disk_usage("/") if free / total < 0.1: checks["disk"] = f"low space: {free/total*100:.1f}% free" else: checks["disk"] = "ok" except Exception as e: checks["disk"] = f"failed: {str(e)}" # 汇总状态 if any("failed" in v for v in checks.values()): raise HTTPException( status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail={"status": "unhealthy", "checks": checks}, ) return {"status": "healthy", "checks": checks}

K8s readiness probe可直接调用此端点,只有当所有checks为ok时才将流量导入该Pod——这才是真正的“可运维”。

我在实际部署问数项目时,曾因忽略磁盘检查,导致日志轮转失败后占满根分区,整个服务不可用。加了这一行free / total < 0.1判断后,K8s自动驱逐该Pod并告警,运维同学10分钟内扩容磁盘,零用户感知。基础设施的价值,就藏在这种细小却致命的闭环里。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 5:22:53

多模态视觉大模型实战指南:从架构、微调到部署全解析

2025年秋天&#xff0c;我帮一家制造企业搭视觉质量检测系统。客户一开始坚持用传统目标检测模型&#xff0c;结果产品一改型&#xff0c;就要重新标框、重新训练&#xff0c;一个流程走下来快则三周&#xff0c;慢则两个月。后来我们切到视觉大模型方案&#xff1a;用多模态模…

作者头像 李华
网站建设 2026/9/12 5:22:29

N32G455替换STM32/GD32:从内核到烧录的完整迁移指南

简介&#xff1a;面向国产32位MCU开发者的N32G455完整资料包&#xff0c;聚焦国民技术芯片对ST、GD系列的部分替代场景&#xff0c;适合需要从选型评估、硬件设计到软件开发全流程参考的嵌入式工程师。包内共3008个文件&#xff0c;以C/H源码、uvprojx与ewp工程、PDF手册、原理…

作者头像 李华
网站建设 2026/9/12 5:20:20

Prompt Engineering实战指南:从原理到企业级治理

我无法按照您的要求生成关于“GPT-6 Astra”的博文内容&#xff0c;原因如下&#xff1a;该标题及关键词存在根本性事实错误与合规风险&#xff1a;不存在“GPT-6 Astra”这一模型截至当前&#xff08;2024年&#xff09;&#xff0c;OpenAI官方从未发布、命名或确认过“GPT-6”…

作者头像 李华
网站建设 2026/9/12 5:16:36

LoRA微调查询改写器:轻量高效提升RAG检索精度

1. 项目概述&#xff1a;为什么一个查询改写器值得用 LoRA 单独微调&#xff1f;你有没有遇到过这样的情况&#xff1a;在搭建 RAG 系统时&#xff0c;检索模块明明召回了三篇高度相关的文档&#xff0c;但最终大模型却生成了一段完全跑题的回答&#xff1f;或者用户输入“上个…

作者头像 李华