Embedding 模型-text2vec python服务化

前言

  如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
  而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!


Embedding 模型-text2vec python服务化

1. 安装 PyTorch:

text2vec 依赖 PyTorch( torch 库),所以需要安装PyTorch。

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu

下载成功:
在这里插入图片描述
验证:

python -c "import torch; print(torch.__version__)"

在这里插入图片描述

2. Embedding 模型-text2vec python demo

模型:
在这里插入图片描述
核心代码:

# 引入 FastAPI 主框架和异常处理类
from fastapi import FastAPI, HTTPException
# 引入 Pydantic,用于请求体/响应体的数据结构校验
from pydantic import BaseModel
# 引入类型注解:List 是列表类型(泛型)
from typing import List
# 引入 text2vec 模型,提供中文句子向量化能力
from text2vec import SentenceModel
import uvicorn
import socket
from common.LogConfig import setup_logger
from fastapi.responses import JSONResponse
from fastapi.requests import Request

import pathlib
import configparser

# 日志和配置初始化
current_dir = pathlib.Path(__file__).parent
config_file = current_dir / 'config' / 'text2vec.ini'
config = configparser.ConfigParser()

try:
    with open(config_file, 'r', encoding='utf-8') as f:
        config.read_file(f)
except Exception as e:
    raise RuntimeError(f"配置文件读取失败: {config_file}, 错误: {str(e)}")

log_file = current_dir / config['logging']['log_file']
log_level = config['logging'].get('log_level', 'INFO').upper()
backup_count = config['logging'].getint('backup_count', 5)
logger_name = config['logging'].get('logger_name', 'text2vec')

embedding_model = config['text2vec'].get('embedding_model', 'shibing624/text2vec-base-chinese')

# 初始化日志配置
log_file.parent.mkdir(parents=True, exist_ok=True)
logger = setup_logger(
    logger_name=logger_name,
    log_file=log_file,
    backup_count=backup_count,
    level_str=log_level
)

# 创建一个 FastAPI 实例,用于定义和启动 Web 服务
app = FastAPI(
    title="Text2Vec Embedding Service",  # API 标题,用于 Swagger 文档展示
    version="1.0"                         # API 版本号
)


# 加载 sentence embedding 模型(中文),第一次运行会自动从 HuggingFace 下载
model = SentenceModel(embedding_model)


# 定义请求数据模型(结构),使用 Pydantic 进行类型检查和自动文档生成
class EmbeddingRequest(BaseModel):
    sentences: List[str]  # 用户传入的句子列表,例如 ["你好", "天气真好"]


# 定义响应数据模型(结构),同样用于类型提示和文档生成
class EmbeddingResponse(BaseModel):
    success: bool                  # 表示接口调用是否成功,比如 True 或 False
    ip: str                       # 请求方的 IP 地址
    msg: str                      # 请求消息
    status_code: int              # 返回码
    vectors: List[List[float]]    # 嵌入向量,二维浮点数组


def get_server_ip():
    """更稳定的本机IP获取方式:通过连接外部服务器获取"""
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))  # 可连接任意外部IP,无需实际发送
        ip = s.getsockname()[0]
        s.close()
        return ip
    except Exception as exc:
        logger.error(f"获取本机IP方式失败: {str(exc)}")
        return "127.0.0.1"


# 定义一个健康检查接口(GET请求),用于探测服务是否存活
@app.get("/health")
async def health_check():
    return {"status": "ok"}  # 返回一个简单的 JSON 表示服务正常


# 定义主接口:将句子转为向量(POST 请求),自动返回 EmbeddingResponse 格式的数据
@app.post("/embed", response_model=EmbeddingResponse)
async def get_embedding(body: EmbeddingRequest):
    # 如果用户传入的是空列表,抛出 HTTP 400(Bad Request)异常
    server_ip = get_server_ip()

    if not body.sentences:
        logger.warning('url:/embed, 请求为空')
        return EmbeddingResponse(status_code=1001,
                                 success=False,
                                 ip=server_ip,
                                 msg="Input 'sentences' cannot be empty.",
                                 vectors=[]
                                 )

    try:
        # 使用模型对句子列表进行向量化,返回为二维数组(多个句子的向量)
        vectors = model.encode(body.sentences).tolist()
        logger.info('url:/embed,查询成功')

        # 返回 JSON 格式结果,符合 response_model 中定义的格式
        return EmbeddingResponse(status_code=200,
                                 success=True,
                                 ip=server_ip,
                                 msg='查询成功',
                                 vectors=vectors)

    except Exception as exc:
        logger.error(f"url:/embed, 查询失败: {str(exc)}")

        return EmbeddingResponse(status_code=500,
                                 success=False,
                                 ip=server_ip,
                                 msg=f"Model error: {str(exc)}",
                                 vectors=[])


# 全局异常拦截
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
    logger.exception(f"[GlobalException] path={request.url.path}, error={str(exc)}")
    return JSONResponse(status_code=500, content={
        "success": False,
        "msg": "Internal server error",
        "status_code": 500,
        "ip": get_server_ip(),
        "vectors": []
    })


if __name__ == "__main__":
    # reload=True 是开发模式;正式部署推荐关闭
    uvicorn.run("text2vec_server:app", host="0.0.0.0", port=8000, reload=True)

启动:
在这里插入图片描述
注意:
第一次运行时,程序会自动去 huggingface 的模型仓库下载对应模型文件和词表文件到本地缓存(一般在 C:\Users<用户名>.cache\huggingface\hub)

测试:
http://127.0.0.1:8000/docs
在这里插入图片描述
监控检查接口:
在这里插入图片描述
向量转换接口:
在这里插入图片描述
在这里插入图片描述
日志:
在这里插入图片描述

3. 内网离线部署

将我们下载好的模型
在这里插入图片描述
手动复制缓存文件到 内网机器相应的缓存目录( .cache/huggingface 目录(或者里面的 hub 子目录) )下,在内网启动程序时,会先检查本地缓存,发现模型文件已经存在,就不会再去网络下载。 这样就可以实现离线加载,避免内网无法联网的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

栗子~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值