清远做网站seo网络文化经营许可证流程
2026/4/17 19:26:14 网站建设 项目流程
清远做网站seo,网络文化经营许可证流程,网站建设优化安徽,永年做网站多少钱bge-large-zh-v1.5代码实例#xff1a;FastAPI封装embedding服务并添加鉴权 1. 为什么需要自己封装embedding服务 你可能已经用过现成的embedding服务#xff0c;比如通过sglang直接暴露的OpenAI兼容接口。但实际项目中#xff0c;你会发现几个绕不开的问题#xff1a;接…bge-large-zh-v1.5代码实例FastAPI封装embedding服务并添加鉴权1. 为什么需要自己封装embedding服务你可能已经用过现成的embedding服务比如通过sglang直接暴露的OpenAI兼容接口。但实际项目中你会发现几个绕不开的问题接口没有权限控制任何人都能调用返回格式和业务系统不匹配缺少统一的日志、监控和错误处理无法灵活扩展预处理或后处理逻辑。这时候一个轻量、可控、可维护的封装层就变得特别重要。本文不讲大道理只带你一步步用FastAPI把bge-large-zh-v1.5这个高质量中文embedding模型包装成一个带鉴权、易集成、生产就绪的服务——所有代码都能直接运行每一步都有明确目的不堆砌概念不绕弯子。2. bge-large-zh-v1.5模型能力再认识bge-large-zh-v1.5不是“又一个中文向量模型”它是当前中文语义理解任务中精度和鲁棒性兼顾得比较好的选择之一。它不是靠参数量堆出来的而是靠更精细的训练策略和中文语料优化出来的。它真正好用的地方藏在细节里不是所有512长度都一样它对长文本的截断和注意力分配做了专门优化比如处理一段300字的产品描述时不会像某些模型那样把关键卖点“稀释”掉向量不是越长越好而是越准越好它输出1024维向量但每一维都在为语义区分服务实测在电商搜索、法律条款比对、客服工单聚类等任务中余弦相似度排序稳定性明显高于同级别模型中文不是英文的影子它没用简单翻译英文指令微调而是用大量真实中文对话、百科、技术文档做对比学习所以对“微信小程序怎么接入支付”和“微信支付接入小程序流程”这类语义近似但字面差异大的query召回更稳。这些能力只有当你把它真正放进自己的服务链路里才能持续发挥价值。而封装就是让它从“能用”变成“好用”的第一步。3. 基于sglang部署的embedding服务现状你已经在服务器上用sglang成功启动了bge-large-zh-v1.5这很好。现在它正通过http://localhost:30000/v1提供OpenAI风格的embedding接口api_keyEMPTY只是占位符实际没有任何校验。我们来快速验证一下它是否真的在工作cd /root/workspace cat sglang.log如果日志末尾出现类似INFO: Uvicorn running on http://0.0.0.0:30000和Loaded model: bge-large-zh-v1.5说明服务已就绪。再用Jupyter快速测试一次调用import openai client openai.Client( base_urlhttp://localhost:30000/v1, api_keyEMPTY ) response client.embeddings.create( modelbge-large-zh-v1.5, input今天天气不错适合写代码 ) print(f向量维度{len(response.data[0].embedding)}) print(f前5个值{response.data[0].embedding[:5]})你会看到输出一个长度为1024的浮点数列表——这就是bge-large-zh-v1.5为你生成的语义指纹。但请注意这个接口是裸奔的。没有身份识别没有调用频控没有请求审计也没有适配你内部系统的字段命名。它是一辆性能不错的车但还没有方向盘、刹车和仪表盘。4. FastAPI封装从零开始构建安全embedding服务我们不用重写模型推理逻辑而是站在sglang肩膀上加一层“智能网关”。这一层要完成三件事鉴权拦截、请求适配、响应标准化。4.1 环境准备与依赖安装新建一个项目目录安装核心依赖mkdir embedding-api cd embedding-api pip install fastapi uvicorn python-jose[cryptography] passlib python-multipart这里选python-jose而不是pyjwt是因为它对中文字符和特殊符号的兼容性更好避免后续在token解析时出莫名其妙的编码错误。4.2 配置管理把密钥和地址从代码里摘出来创建config.py统一管理所有可变参数# config.py from pydantic import BaseSettings class Settings(BaseSettings): # sglang服务地址必须和你实际部署的一致 EMBEDDING_BASE_URL: str http://localhost:30000/v1 # API密钥生产环境建议从环境变量读取 API_KEY: str your-secret-api-key-here # JWT密钥用于生成和校验token SECRET_KEY: str change-this-in-production-very-very-very-long-key # token有效期小时 ACCESS_TOKEN_EXPIRE_MINUTES: int 1440 # 24小时 class Config: case_sensitive False settings Settings()这样做的好处是换环境只需改配置不用动一行业务逻辑。4.3 鉴权模块用JWT实现轻量级身份验证创建auth.py实现标准的Bearer Token校验# auth.py from datetime import datetime, timedelta from typing import Optional, Dict, Any from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from jose import JWTError, jwt from passlib.context import CryptContext from config import settings oauth2_scheme OAuth2PasswordBearer(tokenUrltoken) pwd_context CryptContext(schemes[bcrypt], deprecatedauto) def verify_api_key(api_key: str) - bool: 校验原始API密钥用于首次登录 return api_key settings.API_KEY def create_access_token(data: Dict[str, Any], expires_delta: Optional[timedelta] None) - str: 生成JWT token to_encode data.copy() if expires_delta: expire datetime.utcnow() expires_delta else: expire datetime.utcnow() timedelta(minutes15) to_encode.update({exp: expire}) encoded_jwt jwt.encode(to_encode, settings.SECRET_KEY, algorithmHS256) return encoded_jwt async def get_current_user(token: str Depends(oauth2_scheme)) - str: 从token中解析用户标识这里简化为固定字符串 credentials_exception HTTPException( status_codestatus.HTTP_401_UNAUTHORIZED, detail无法验证凭据, headers{WWW-Authenticate: Bearer}, ) try: payload jwt.decode(token, settings.SECRET_KEY, algorithms[HS256]) user_id: str payload.get(sub) if user_id is None: raise credentials_exception except JWTError: raise credentials_exception return user_id注意这里没有引入数据库用户表因为大多数内部服务只需要“有密钥就能用”够用且轻量。4.4 核心服务调用sglang并标准化响应创建services/embedding_service.py专注做一件事把OpenAI格式转成你想要的格式。# services/embedding_service.py import httpx from typing import List, Dict, Any from config import settings async def get_embedding(text: str, model_name: str bge-large-zh-v1.5) - List[float]: 调用sglang embedding服务返回纯向量列表 async with httpx.AsyncClient() as client: try: response await client.post( f{settings.EMBEDDING_BASE_URL}/embeddings, json{ model: model_name, input: text }, timeout30.0 ) response.raise_for_status() data response.json() # 提取第一个结果的向量支持批量输入时可扩展 return data[data][0][embedding] except httpx.HTTPStatusError as e: raise HTTPException( status_codee.response.status_code, detailfsglang服务返回错误: {e.response.text} ) except Exception as e: raise HTTPException( status_code500, detailf调用embedding服务失败: {str(e)} ) # 批量处理函数可选按需启用 async def get_embeddings_batch(texts: List[str], model_name: str bge-large-zh-v1.5) - List[List[float]]: async with httpx.AsyncClient() as client: try: response await client.post( f{settings.EMBEDDING_BASE_URL}/embeddings, json{ model: model_name, input: texts }, timeout60.0 ) response.raise_for_status() data response.json() return [item[embedding] for item in data[data]] except Exception as e: raise HTTPException(status_code500, detailstr(e))这个模块的关键设计点使用httpx.AsyncClient保持异步非阻塞避免拖慢整个API错误分类处理网络错误、HTTP错误、JSON解析错误分别给出清晰提示返回值是干净的List[float]不带任何OpenAI的wrapper字段下游系统拿来就能用。4.5 主应用组装路由与中间件创建main.py这是整个服务的入口# main.py from fastapi import FastAPI, Depends, HTTPException, status, Request from fastapi.responses import JSONResponse from typing import List, Dict, Any from auth import get_current_user, create_access_token, verify_api_key from services.embedding_service import get_embedding, get_embeddings_batch from config import settings import time app FastAPI( titleBGE中文Embedding服务, description基于bge-large-zh-v1.5的FastAPI封装含JWT鉴权与标准化响应, version1.0.0 ) # 全局请求耗时记录中间件 app.middleware(http) async def add_process_time_header(request: Request, call_next): start_time time.time() response await call_next(request) process_time time.time() - start_time response.headers[X-Process-Time] str(process_time) return response # 登录接口用原始API密钥换取JWT token app.post(/token, summary获取访问令牌) async def login_for_access_token(api_key: str): if not verify_api_key(api_key): raise HTTPException( status_codestatus.HTTP_401_UNAUTHORIZED, detail无效的API密钥, headers{WWW-Authenticate: Bearer}, ) access_token_expires timedelta(minutessettings.ACCESS_TOKEN_EXPIRE_MINUTES) access_token create_access_token( data{sub: embedding-service-user}, expires_deltaaccess_token_expires ) return {access_token: access_token, token_type: bearer} # 单文本embedding接口 app.post(/v1/embeddings, summary获取单文本向量) async def embed_text( request: Dict[str, Any], current_user: str Depends(get_current_user) ): 输入{text: 待向量化文本, model: 可选默认bge-large-zh-v1.5} 输出{vector: [0.12, -0.45, ...], dimension: 1024, model: bge-large-zh-v1.5} text request.get(text) if not text or not isinstance(text, str) or not text.strip(): raise HTTPException(status_code400, detailtext字段不能为空字符串) model_name request.get(model, bge-large-zh-v1.5) vector await get_embedding(text, model_name) return { vector: vector, dimension: len(vector), model: model_name, text_length: len(text) } # 批量embedding接口可选 app.post(/v1/embeddings/batch, summary批量获取文本向量) async def embed_batch( request: Dict[str, Any], current_user: str Depends(get_current_user) ): texts request.get(texts) if not texts or not isinstance(texts, list): raise HTTPException(status_code400, detailtexts字段必须是非空列表) model_name request.get(model, bge-large-zh-v1.5) vectors await get_embeddings_batch(texts, model_name) return { vectors: vectors, count: len(vectors), dimension: len(vectors[0]) if vectors else 0, model: model_name } # 健康检查接口 app.get(/health, summary服务健康状态) async def health_check(): return {status: ok, timestamp: int(time.time())}这个main.py体现了几个工程化细节/token接口只做密钥校验和token发放不涉及模型调用极快/v1/embeddings返回的是扁平化的JSON没有嵌套的data、object等OpenAI字段前端解析零成本加了全局中间件记录耗时方便后续做性能分析每个接口都有清晰的summary和request示例注释Swagger UI自动生成文档。5. 启动与验证三步走通整条链路5.1 启动FastAPI服务在项目根目录执行uvicorn main:app --host 0.0.0.0 --port 8000 --reload服务启动后访问http://你的服务器IP:8000/docs就能看到自动生成的交互式API文档。5.2 获取访问令牌用curl测试登录curl -X POST \ http://localhost:8000/token \ -H Content-Type: application/json \ -d your-secret-api-key-here你会得到类似这样的响应{ access_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJlbWJlZGRpbmctc2VydmljZS11c2VyIiwiZXhwIjoxNzY4Mjk3MTIwfQ.xxxxx, token_type: bearer }复制access_token的值后面调用要用。5.3 调用embedding接口用获取到的token调用向量化curl -X POST \ http://localhost:8000/v1/embeddings \ -H accept: application/json \ -H Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... \ -H Content-Type: application/json \ -d { text: 人工智能正在改变软件开发方式, model: bge-large-zh-v1.5 }你会收到一个简洁的响应{ vector: [0.234, -0.156, 0.892, ...], dimension: 1024, model: bge-large-zh-v1.5, text_length: 14 }对比sglang原生接口返回的嵌套结构这个结果是不是更清爽、更易集成6. 进阶建议让服务更贴近生产环境这套方案已经可以跑起来但如果你打算长期使用还有几个小但关键的优化点日志结构化把print()换成logging并加入request_id方便问题追踪限流保护用slowapi给/v1/embeddings加个每分钟100次的限制防误用模型热切换在config.py里加个MODEL_ALIASES映射表比如{default: bge-large-zh-v1.5, legal: bge-reranker-base}让不同业务线用不同模型向量缓存对高频重复文本如产品标题、FAQ问题加一层Redis缓存减少GPU计算压力监控埋点在get_embedding函数里加Prometheus指标上报统计QPS、P95延迟、错误率。这些都不是必须一步到位的而是随着你的使用场景变复杂自然浮现出来的需求。你现在最需要的是一个能立刻跑起来、看得见效果、改起来不费劲的起点——本文给你的正是这个起点。7. 总结封装不是重复造轮子而是掌控力的延伸把bge-large-zh-v1.5封装进FastAPI看起来只是加了一层HTTP转发但实际收获远不止于此安全可控不再担心谁都能调用你的GPU资源协议自主告别OpenAI兼容的束缚定义你自己的输入输出规范可观测性每个请求都有日志、有耗时、有状态码出了问题不再两眼一抹黑演进空间今天加鉴权明天加缓存后天加重试策略全由你决定节奏。技术的价值从来不在“能不能跑”而在“能不能稳、能不能扩、能不能管”。当你亲手把一个强大模型变成自己系统里一个可信赖的组件时那种掌控感是任何现成服务都无法替代的。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询