PI-LLM-Server - 统一 LLM 服务网关
为 OpenClaw、Claude Code 等 AI 编程助手提供本地化的 Embedding、ASR、Reranker、OCR 等服务
问题背景: 阿里云等 Coding Plan 产品提供了大模型 API,但未包含 Embedding、Reranker、ASR、OCR 等辅助服务。这些模型通常较小,可本地部署以获得更低延迟和更好的隐私保护。
解决方案: PI-LLM-Server 统一管理多种本地服务,提供标准化 API 网关,为 AI 编程助手提供一站式服务接入。还支持接入 pi-memory 记忆管理和知识库搜索服务。
目录
项目目的
PI-LLM-Server 旨在解决以下问题:
- 服务碎片化: Embedding、ASR、Reranker、OCR 等服务分散部署,管理复杂
- API 不统一: 各服务接口风格不一致,集成成本高
- 缺少队列管理: 并发请求可能导致显存溢出或服务崩溃
- 缺乏健康监控: 服务异常时无法自动发现和恢复
通过本项目,您可以:
- 统一管理多个 AI 子服务,提供一致的服务入口
- 配置请求队列,防止并发过载
- 启用 API 访问控制,保护服务安全
- 实时监控服务健康状态
- 为 OpenClaw、Claude Code 等工具提供本地化服务支持
快速开始
1. 环境准备
详细的 conda 安装可以参考: 安装Python环境
# 创建 Conda 环境
conda create -n pi-llm-server python=3.13
conda activate pi-llm-server
2. 安装项目
# 通过pip安装(推荐), pip install uv
uv pip install pi-llm-server[all]
# 源码安装: 进入项目目录安装
cd pi-llm-server
uv pip install -e ".[all]"
# 方式 2: 只安装核心服务(按需选择)
uv pip install -e ".[embedding,reranker,asr,mineru]"
3. 系统依赖
其他软件包
sudo apt-get install -y libreoffice-java-common
CUDA Toolkit 安装(需要 GPU 时使用)
# 访问 NVIDIA CUDA 下载页面
# https://developer.nvidia.com/cuda-toolkit-archive
# 或使用快捷链接(例如 CUDA 12.8)
# https://developer.nvidia.com/cuda-12-8-1-download-archive
# 安装后创建符号链接(如需要)
cd /usr/bin
sudo ln -s /usr/local/cuda-12.8/bin/nvcc nvcc
# 设置环境变量,把如下的内容放入 /etc/bash.bashrc (如果使用的是bash,其他的sh类似)
export CUDA_HOME=/usr/local/cuda-12.8
export PATH=$CUDA_HOME/bin:$CUDA_HOME/nvvm/bin:$PATH
export CPLUS_INCLUDE_PATH=$CUDA_HOME/include:$CPLUS_INCLUDE_PATH
export LIBRARY_PATH=$CUDA_HOME/lib64:$LIBRARY_PATH
export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH
模型下载
方式 1: 使用 ModelScope 下载(推荐国内用户)
# Embedding 模型
modelscope download --model unsloth/Qwen3-Embedding-0.6B
# ASR 模型
modelscope download --model Qwen/Qwen3-ASR-1.7B
# Reranker 模型
modelscope download --model Qwen/Qwen3-Reranker-0.6B
方式 2: 模型存储位置
ModelScope 模型默认下载到:
~/.cache/modelscope/hub/models/<组织>/<模型名>
例如:
- Embedding:
~/.cache/modelscope/hub/models/unsloth/Qwen3-Embedding-4B - ASR:
~/.cache/modelscope/hub/models/Qwen/Qwen3-ASR-1.7B - Reranker:
~/.cache/modelscope/hub/models/Qwen/Qwen3-Reranker-0.6B
方式 3: 使用 HuggingFace(需要网络条件)
# 使用 huggingface-cli 下载
huggingface-cli download unsloth/Qwen3-Embedding-4B --local-dir ~/.cache/huggingface/hub/models/unsloth/Qwen3-Embedding-4B
使用方法
1. 配置目录结构
首次运行时会自动创建配置文件,无需手动复制:
# 首次运行时会自动创建配置目录和配置文件
# 配置文件位置:~/.config/pi-llm-server/config.yaml
如需手动配置,可以从包内复制示例配置:
# 创建配置目录
mkdir -p ~/.config/pi-llm-server
# 从已安装的包中复制示例配置(如果自动创建失败)
cp $(python -c "from pathlib import Path; import pi_llm_server; print(Path(pi_llm_server.__file__).parent / 'examples' / 'config.example.yaml')") ~/.config/pi-llm-server/config.yaml
2. 编辑配置文件
如果使用的模型和上面下载的不同,需要编辑 ~/.config/pi-llm-server/config.yaml,主要配置项:
server:
host: "0.0.0.0"
port: 8090
auth:
enabled: true
tokens:
- "your-api-token-here"
services:
embedding:
enabled: true
base_url: "http://127.0.0.1:8091"
asr:
enabled: true
base_url: "http://127.0.0.1:8092"
reranker:
enabled: true
base_url: "http://127.0.0.1:8093"
mineru:
enabled: true
base_url: "http://127.0.0.1:8094"
3. 启动服务
方式 A: 一站式启动(推荐)
# 启动所有服务(后台服务 + 统一网关)
pi-llm-server start-all
# 查看所有服务状态
pi-llm-server status
# 停止所有服务
pi-llm-server stop-all
方式 B: 仅启动统一网关
方式 B: 仅启动统一网关
# 使用命令行工具启动网关服务
pi-llm-server
# 或指定配置
pi-llm-server --config ~/.config/pi-llm-server/config.yaml --port 8090
# 后台运行
nohup pi-llm-server > ~/.cache/pi-llm-server/logs/gateway.log 2>&1 &
方式 C: 后台服务管理
# 启动所有后台服务
pi-llm-server services start --all
# 查看服务状态
pi-llm-server services status
# 停止所有后台服务
pi-llm-server services stop --all
# 单独启动/停止某个服务
pi-llm-server services start embedding
pi-llm-server services stop asr
方式 D: 使用 systemd 服务(生产环境推荐)
自动安装(推荐):
# 运行自动配置脚本,会检测当前环境并生成合适的配置
cd pi-llm-server
bash pi_llm_server/examples/install-service.sh
脚本会自动:
- 检测当前用户和组
- 检测 Python/Conda 环境路径
- 检测项目安装模式(pip 或源码)
- 生成合适的 service 文件并安装
手动配置:
# 1. 复制模板文件
cp pi_llm_server/examples/pi-llm-server.service.template /tmp/pi-llm-server.service
# 2. 编辑模板,替换以下占位符:
# - YOUR_USERNAME -> 你的用户名(运行 whoami 获取)
# - YOUR_GROUPNAME -> 你的用户组(运行 id -gn 获取)
# - /path/to/python -> Python 路径(运行 which python 获取)
# - WorkingDirectory(源码模式需要,pip 安装可删除此行)
nano /tmp/pi-llm-server.service
# 3. 安装到 systemd
sudo mv /tmp/pi-llm-server.service /etc/systemd/system/pi-llm-server.service
sudo systemctl daemon-reload
# 4. 管理服务
sudo systemctl start pi-llm-server
sudo systemctl enable pi-llm-server
服务管理命令:
# 启动服务
sudo systemctl start pi-llm-server
# 设置开机自启
sudo systemctl enable pi-llm-server
# 查看服务状态
sudo systemctl status pi-llm-server
# 查看日志
sudo journalctl -u pi-llm-server -f
# 停止服务
sudo systemctl stop pi-llm-server
# 卸载服务
sudo systemctl disable pi-llm-server
sudo rm /etc/systemd/system/pi-llm-server.service
sudo systemctl daemon-reload
方式 E: 手动启动子服务(开发调试用)
# Embedding 服务
python pi_llm_server/launcher/embedding_server.py --model-path ~/.cache/modelscope/hub/models/unsloth/Qwen3-Embedding-0.6B --device cpu
# ASR 服务(需要 GPU)
python pi_llm_server/launcher/asr_server.py --model-path ~/.cache/modelscope/hub/models/Qwen/Qwen3-ASR-1.7B
# Reranker 服务
python pi_llm_server/launcher/reranker_server.py --model-path ~/.cache/modelscope/hub/models/Qwen/Qwen3-Reranker-0.6B --device cpu
# MinerU 服务
# 注意:MinerU 需要 GPU 支持,建议使用独立显存(9GB 以上)
./mineru_server.sh start --python-path /path/to/python
4. 验证服务
# 健康检查
curl http://localhost:8090/health
# 列出可用模型
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8090/v1/models
# 例如
curl -H "Authorization: Bearer sk-5f8b839908d14561590b70227c72ca86" http://localhost:8090/v1/models
# 生成 Embedding
curl -X POST http://localhost:8090/v1/embeddings \
-H "Authorization: Bearer sk-your-token" \
-H "Content-Type: application/json" \
-d '{"input": "你好,世界!"}'
5. Python 客户端示例
项目提供了完整的 Python 使用示例 pi_llm_server/examples/basic_usage.py:
主要功能:
- 健康检查和服务状态查询
- 生成 Embedding(支持 float 和 base64 编码格式)
- 文档重排序(Reranker)
- 语音转文字(ASR)
- PDF 解析(MinerU/OCR)
运行示例:
# 确保服务已启动
pi-llm-server status
# 运行示例程序
python pi_llm_server/examples/basic_usage.py
示例代码结构:
"""
PI-LLM-Server 基本使用示例
本示例展示如何使用 Python 客户端调用 PI-LLM-Server 提供的服务。
"""
import httpx
import base64
# 服务地址
BASE_URL = "http://127.0.0.1:8090"
# API Token(从配置文件获取)
API_TOKEN = "sk-5f8b839908d14561590b70227c72ca86"
# 请求头
HEADERS = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json",
}
def generate_embedding(text: str, model: str = "unsloth/Qwen3-Embedding-0.6B", encoding_format: str = "float"):
"""生成文本 embedding
Args:
text: 输入文本
model: 模型名称
encoding_format: 编码格式,支持 "float" 或 "base64"
"""
payload = {
"model": model,
"input": [text],
"encoding_format": encoding_format,
}
response = httpx.post(
f"{BASE_URL}/v1/embeddings",
json=payload,
headers=HEADERS,
timeout=60,
)
result = response.json()
if encoding_format == "base64":
# base64 格式,解码并显示预览
import struct
embedding_data = result['data'][0]['embedding']
decoded = base64.b64decode(embedding_data)
float_count = len(decoded) // 4 # float32 占 4 字节
floats = struct.unpack(f'{float_count}f', decoded)
print(f"Embedding 维度:{len(floats)} (base64 编码)")
print(f"向量预览 (前 10 个值): {floats[:10]}")
else:
# float 格式
print(f"Embedding 维度:{len(result['data'][0]['embedding'])}")
return result
def rerank_documents(query: str, documents: list):
"""对文档进行重排序"""
payload = {
"query": query,
"documents": documents,
}
response = httpx.post(
f"{BASE_URL}/v1/rerank",
json=payload,
headers=HEADERS,
timeout=120,
)
result = response.json()
print("重排序结果:")
for item in result.get("results", []):
print(f" 文档 {item['index']}: 得分 {item['relevance_score']:.4f}")
return result
def transcribe_audio(audio_path: str):
"""语音转文字 (ASR)"""
with open(audio_path, "rb") as f:
audio_data = f.read()
files = {"file": ("audio.mp3", audio_data, "audio/mpeg")}
response = httpx.post(
f"{BASE_URL}/v1/audio/transcriptions",
files=files,
headers={"Authorization": f"Bearer {API_TOKEN}"},
timeout=300,
)
result = response.json()
print("转录结果:", result.get("text", ""))
return result
def parse_pdf(pdf_path: str):
"""解析 PDF 文件 (MinerU/OCR)"""
with open(pdf_path, "rb") as f:
pdf_data = f.read()
files = {"files": ("document.pdf", pdf_data, "application/pdf")}
response = httpx.post(
f"{BASE_URL}/v1/ocr/parser",
files=files,
headers={"Authorization": f"Bearer {API_TOKEN}"},
timeout=600,
)
print(f"PDF 解析完成,ZIP 大小:{len(response.content)} bytes ({len(response.content) / 1024 / 1024:.2f} MB)")
return response.content
测试数据文件:
示例程序使用以下测试文件(需自行准备):
data/audio_s.mp3- ASR 语音识别测试data/InfoLOD.pdf- PDF 解析测试
命令行工具
安装后可以使用 pi-llm-server 命令:
# 查看所有命令
pi-llm-server --help
# 一站式启动所有服务(后台服务 + 网关)
pi-llm-server start-all
# 一站式停止所有服务
pi-llm-server stop-all
# 查看所有服务状态
pi-llm-server status
# 后台服务管理(start/stop/restart/status)
pi-llm-server services start --all
pi-llm-server services stop --all
pi-llm-server services status
# 仅启动网关(默认行为)
pi-llm-server
pi-llm-server --port 8090
pi-llm-server --config ~/.config/pi-llm-server/config.yaml
命令说明
| 命令 | 说明 |
|---|---|
start-all |
一站式启动所有服务(后台服务 + 统一网关) |
stop-all |
一站式停止所有服务(网关 + 后台服务) |
status |
查看所有服务状态(网关 + 后台服务) |
services |
后台服务管理(start/stop/restart/status) |
| 无命令 | 仅启动统一网关(默认行为) |
配置说明
配置文件位置
- 默认路径:
~/.config/pi-llm-server/config.yaml - 可通过
--config参数指定其他路径 - 首次运行时会自动从包内复制示例配置文件
主要配置项
| 配置项 | 说明 | 默认值 |
|---|---|---|
server.host |
监听地址 | 0.0.0.0 |
server.port |
监听端口 | 8090 |
server.workers |
工作进程数 | 4 |
server.log_level |
日志级别 | info |
auth.enabled |
是否启用认证 | true |
auth.tokens |
有效 Token 列表 | [] |
queue.enabled |
是否启用队列 | true |
queue.default.max_size |
默认队列大小 | 100 |
queue.default.max_concurrent |
默认并发数 | 1 |
queue.default.timeout_seconds |
默认超时时间 | 300 |
services.*.enabled |
是否启用子服务 | true |
services.*.base_url |
子服务地址 | 需配置 |
services.memory.base_url |
pi-memory 服务地址 | http://agent.adv-ci.com:9873 |
services.memory.api_key |
pi-memory API Key | 无 |
health_check.enabled |
是否启用健康检查 | true |
health_check.interval_seconds |
健康检查间隔 | 30 |
health_check.unhealthy_threshold |
不健康判定阈值 | 3 |
配置文件示例
完整配置示例请参考 pi_llm_server/examples/config.example.yaml:
# =============================================
# 服务基础配置
# =============================================
server:
host: "0.0.0.0"
port: 8090
workers: 4
log_level: "info"
# =============================================
# API 访问控制
# =============================================
auth:
enabled: true
tokens:
- "sk-5f8b839908d14561590b70227c72ca86"
# =============================================
# 请求队列配置 - 差异化策略
# =============================================
queue:
enabled: true
default:
max_size: 100
max_concurrent: 1
timeout_seconds: 300
services:
embedding:
max_concurrent: 1
max_size: 200
timeout_seconds: 60
reranker:
max_concurrent: 4
max_size: 200
timeout_seconds: 120
asr:
max_concurrent: 1
max_size: 50
timeout_seconds: 600
mineru:
max_concurrent: 1
max_size: 20
timeout_seconds: 1800
# =============================================
# 子服务配置
# =============================================
services:
embedding:
enabled: true
base_url: "http://127.0.0.1:8091"
models:
- id: "unsloth/Qwen3-Embedding-0.6B"
path: "~/.cache/modelscope/hub/models/unsloth/Qwen3-Embedding-0.6B"
device: "cuda"
asr:
enabled: true
base_url: "http://127.0.0.1:8092"
models:
- id: "Qwen/Qwen3-ASR-1.7B"
path: "~/.cache/modelscope/hub/models/Qwen/Qwen3-ASR-1.7B"
gpu_memory_utilization: 0.9
reranker:
enabled: true
base_url: "http://127.0.0.1:8093"
models:
- id: "Qwen/Qwen3-Reranker-0.6B"
path: "~/.cache/modelscope/hub/models/Qwen/Qwen3-Reranker-0.6B"
device: "cpu"
mineru:
enabled: true
base_url: "http://127.0.0.1:8094"
config:
vram: "9000"
model_source: "modelscope"
# pi-memory 服务代理(可选,不写此节不会初始化)
memory:
enabled: true
base_url: "http://agent.adv-ci.com:9873"
timeout_seconds: 30
max_retries: 3
api_key: ""
# =============================================
# 健康检查配置
# =============================================
health_check:
enabled: true
interval_seconds: 30
timeout_seconds: 10
unhealthy_threshold: 3
队列配置策略
| 服务 | 并发数 | 队列大小 | 超时 (秒) | 说明 |
|---|---|---|---|---|
| embedding | 1 | 200 | 60 | GPU 推理,顺序处理避免显存溢出 |
| reranker | 4 | 200 | 120 | CPU 多核并行 |
| asr | 1 | 50 | 600 | GPU 推理,顺序处理避免显存溢出 |
| mineru | 1 | 20 | 1800 | PDF 解析耗时,顺序处理 |
端口分配
| 服务 | 端口 | 说明 |
|---|---|---|
| 统一网关 | 8090 | 主入口 |
| Embedding | 8091 | 文本向量化 |
| ASR | 8092 | 语音识别 |
| Reranker | 8093 | 文档重排序 |
| MinerU | 8094 | PDF 解析 |
| pi-memory | 9873 | 记忆管理 + 知识库(独立部署) |
服务守护进程
PI-LLM-Server 提供独立的服务守护进程 (service_daemon.py),自动监控各子服务健康状态并在服务异常时自动重启。
主要功能
| 功能 | 说明 |
|---|---|
| 推理健康检测 | 使用实际 API 调用验证服务可用,而非仅 HTTP 端点响应 |
| 自动重启 | 连续失败达到阈值(默认 3 次)后自动重启服务 |
| 服务级冷却期 | 防止服务启动期间误判为失败而触发重启 |
| 最大重启限制 | 达到上限(默认 3 次)后停止自动重启,等待人工干预 |
| 状态持久化 | 重启计数和状态保存在 JSON 文件,防止重启循环 |
检测流程
1. HTTP 健康检查 → 调用 /health 端点
2. 推理检测 → 调用实际 API(使用测试数据)
3. 失败计数 → 连续失败达到阈值触发重启
4. 冷却期 → 重启后一段时间内不进行检测
推理检测测试数据
| 服务 | 测试数据 | 说明 |
|---|---|---|
| Embedding | "健康检测测试" |
测试文本调用 Embedding API |
| ASR | 1 秒 WAV 音频 | 16kHz, mono, 16bit 测试音频 |
| Reranker | 测试查询 + 文档列表 | 重排序 API 测试 |
| MinerU | 200x50 PNG 图片 | 图片解析测试 |
守护进程管理
# 一站式启动(守护进程随 start-all 自动启动)
pi-llm-server start-all
# 单独启动守护进程
pi-llm-server services start daemon
# 查看守护进程状态
pi-llm-server status
# 停止守护进程
pi-llm-server services stop daemon
守护进程配置
配置文件 (config.yaml) 新增 daemon 配置节:
daemon:
enabled: true # 是否启用守护进程
check_interval: 30 # 健康检查间隔(秒)
http_timeout: 10 # HTTP 检查超时(秒)
inference_timeout: 5 # 推理检测超时(秒)
unhealthy_threshold: 3 # 连续失败判定阈值
restart_cooldown: 120 # 默认重启后冷却时间(秒)
max_restart_attempts: 3 # 单次最多重启尝试次数
services: # 服务级别配置覆盖
embedding:
restart_cooldown: 60 # 模型加载快
inference_timeout: 3 # 短文本推理快
asr:
restart_cooldown: 180 # GPU 模型加载慢
inference_timeout: 10 # 音频转写需要时间
reranker:
restart_cooldown: 60 # CPU 模型加载较快
inference_timeout: 3 # 短查询推理快
mineru:
restart_cooldown: 120 # PDF 解析服务启动需要时间
inference_timeout: 30 # 图片解析需要时间
配置项说明
| 配置项 | 默认值 | 说明 |
|---|---|---|
enabled |
true |
是否启用守护进程 |
check_interval |
30 |
健康检查间隔(秒) |
http_timeout |
10 |
HTTP 检查超时(秒) |
inference_timeout |
5 |
推理检测超时(秒) |
unhealthy_threshold |
3 |
连续失败多少次判定为不健康 |
restart_cooldown |
120 |
重启后冷却时间(秒),期间不检测 |
max_restart_attempts |
3 |
单次最多重启尝试,达到上限后停止 |
服务级冷却时间
各服务根据启动时间配置不同的冷却期:
| 服务 | 冷却时间 | 说明 |
|---|---|---|
| Embedding | 60 秒 | CPU 模型加载快 |
| ASR | 180 秒 | GPU 模型加载慢,需要 3 分钟 |
| Reranker | 60 秒 | CPU 模型加载较快 |
| MinerU | 120 秒 | PDF 解析服务启动需要时间 |
日志和状态文件
# 守护进程日志
~/.cache/pi-llm-server/logs/daemon.log
# 守护进程 PID 文件
~/.cache/pi-llm-server/pids/daemon.pid
# 守护进程状态文件(重启计数等)
~/.cache/pi-llm-server/daemon_state.json
# 查看守护进程日志
tail -f ~/.cache/pi-llm-server/logs/daemon.log
API 文档
完整的接口定义、请求参数、响应格式和性能建议请参考
docs/api_manual.md。
端点列表
| 端点 | 方法 | 说明 | 认证 |
|---|---|---|---|
/ |
GET | 欢迎信息 | 否 |
/health |
GET | 健康检查 | 否 |
/status |
GET | 详细状态 | 是 |
/v1/models |
GET | 可用模型列表 | 可选 |
/v1/embeddings |
POST | 生成 Embedding | 是 |
/v1/rerank |
POST | 文档重排序 | 是 |
/v1/audio/transcriptions |
POST | 语音转文字 | 是 |
/v1/ocr/parser |
POST | PDF 解析 | 是 |
/memory/api/memory/search |
POST | 记忆搜索 | 是 |
/memory/api/memory/store |
POST | 存储记忆 | 是 |
/memory/api/memory/{id} |
DELETE | 删除记忆 | 是 |
/memory/api/memory/{id} |
PATCH | 更新记忆 | 是 |
/memory/api/memory/list |
GET | 记忆列表 | 是 |
/memory/api/memory/stats |
GET | 记忆统计 | 是 |
/memory/api/knowledge/search |
POST | 知识库搜索 | 是 |
/memory/api/knowledge/index |
POST | 重建知识库索引 | 是 |
/memory/api/knowledge/stats |
GET | 知识库统计 | 是 |
/docs |
GET | Swagger 文档 | 否 |
API 使用示例
1. 生成 Embedding
请求:
curl -X POST http://localhost:8090/v1/embeddings \
-H "Authorization: Bearer sk-your-token" \
-H "Content-Type: application/json" \
-d '{
"model": "unsloth/Qwen3-Embedding-0.6B",
"input": ["你好,世界!"]
}'
响应:
{
"object": "list",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [-0.012, 0.045, ...]
}
],
"model": "unsloth/Qwen3-Embedding-0.6B",
"usage": {
"prompt_tokens": 5,
"total_tokens": 5
}
}
2. 文档重排序 (Rerank)
请求:
curl -X POST http://localhost:8090/v1/rerank \
-H "Authorization: Bearer sk-your-token" \
-H "Content-Type: application/json" \
-d '{
"query": "深度学习",
"documents": [
"人工智能是计算机科学的一个分支",
"机器学习是实现人工智能的方法之一",
"深度学习是机器学习的子集"
]
}'
响应:
{
"model": "Qwen/Qwen3-Reranker-0.6B",
"results": [
{"index": 2, "document": "深度学习是机器学习的子集", "relevance_score": 0.8234},
{"index": 1, "document": "机器学习是实现人工智能的方法之一", "relevance_score": 0.1523},
{"index": 0, "document": "人工智能是计算机科学的一个分支", "relevance_score": 0.0821}
]
}
3. 语音转文字 (ASR)
请求:
curl -X POST http://localhost:8090/v1/audio/transcriptions \
-H "Authorization: Bearer sk-your-token" \
-F "file=@audio.mp3" \
-F "model=Qwen/Qwen3-ASR-1.7B" \
-F "save_srt=true"
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
file |
File | 是 | 音频文件 (mp3/wav/flac/ogg/webm/m4a) |
model |
string | 否 | 模型 ID,默认 Qwen/Qwen3-ASR-1.7B |
context |
string | 否 | 上下文术语,帮助识别专业词汇 |
vad_threshold |
int | 否 | VAD 分割阈值(秒),默认 120 |
save_srt |
bool | 否 | 是否生成 SRT 字幕,默认 false |
响应:
{
"text": "大家好,这里是最佳拍档...",
"srt_content": "1\n00:00:00,162 --> 00:00:13,917\n大家好...\n\n2\n..."
}
- 默认响应仅包含
text字段 - 当
save_srt=true时,额外返回srt_content字段,内容为标准 SRT 字幕格式 - m4a 文件会自动调用 ffmpeg 转换为 wav 后处理
支持的音频格式:
| 格式 | 扩展名 | 说明 |
|---|---|---|
| MP3 | .mp3 |
原生支持 |
| WAV | .wav |
原生支持 |
| FLAC | .flac |
原生支持 |
| OGG | .ogg |
原生支持 |
| WebM | .webm |
原生支持 |
| M4A | .m4a |
通过 ffmpeg 自动转换为 wav |
m4a 依赖:
# Ubuntu/Debian
sudo apt-get install ffmpeg
# macOS (使用 Homebrew)
brew install ffmpeg
4. PDF 解析 (MinerU/OCR)
请求:
curl -X POST http://localhost:8090/v1/ocr/parser \
-H "Authorization: Bearer sk-your-token" \
-F "files=@document.pdf" \
-F "backend=pipeline" \
-F "parse_method=auto" \
-F "lang_list=ch" \
-F "return_md=true" \
-F "return_images=true" \
-o result.zip
响应: ZIP 文件,包含:
markdown/- 解析后的 Markdown 文件images/- 提取的图片- 其他中间文件
支持的文件类型:
| 类型 | 扩展名 | 说明 |
|---|---|---|
.pdf |
原生 PDF 文档 | |
| 图片 | .jpg, .jpeg, .png |
图片文件(自动转换为 PDF 处理) |
| Word 文档 | .docx, .doc |
需要安装 libreoffice 进行转换 |
| PPT 演示文稿 | .pptx, .ppt |
需要安装 libreoffice 进行转换 |
| Excel 表格 | .xlsx, .xls |
需要安装 libreoffice 进行转换 |
Office 文档转换依赖:
# Ubuntu/Debian
sudo apt-get install libreoffice
# macOS (使用 Homebrew)
brew install libreoffice
# CentOS/RHEL
sudo yum install libreoffice
参数说明:
| 参数 | 默认值 | 说明 |
|---|---|---|
backend |
pipeline | 解析后端:pipeline/hybrid-auto-engine/vlm-auto-engine |
parse_method |
auto | 解析方法:auto/txt/ocr |
lang_list |
ch | 语言:ch/en/korean/japan |
return_md |
true | 返回 Markdown |
return_images |
true | 返回图片 |
5. pi-memory 记忆搜索
请求:
curl -X POST http://localhost:8090/memory/api/memory/search \
-H "Authorization: Bearer sk-your-token" \
-H "Content-Type: application/json" \
-d '{"query": "用户偏好设置", "limit": 5}'
6. pi-memory 知识库搜索
请求:
curl -X POST http://localhost:8090/memory/api/knowledge/search \
-H "Authorization: Bearer sk-your-token" \
-H "Content-Type: application/json" \
-d '{"query": "无人机控制", "limit": 10}'
关联项目
VLLM
VLLM 是一个高吞吐、大吞吐量的 LLM 推理和服务引擎。
- 关系: PI-LLM-Server 使用 VLLM 作为 ASR 服务的推理后端
- 区别: VLLM 专注于 LLM 推理引擎,PI-LLM-Server 专注于服务集成和统一管理
- 协作: 可以结合使用,VLLM 提供底层推理能力,PI-LLM-Server 提供上层服务编排
LocalAI
LocalAI 是一个开源的 OpenAI API 替代品,支持多种模型。
- 关系: LocalAI 也是提供本地化 AI 服务的项目
- 区别:
- LocalAI 是"All-in-One"的大而全方案,支持更多模型类型
- PI-LLM-Server 更轻量,专注于 Embedding、ASR、Reranker、OCR 等辅助服务
- PI-LLM-Server 更适合作为其他服务的补充,而非替代
- 协作: 可以与 LocalAI 并存,各自负责不同的服务场景
阿里云百炼/通义灵码
- 背景: 提供大模型 API,但缺少 Embedding、Reranker 等辅助服务
- PI-LLM-Server 定位: 补充这些本地可部署的小模型服务,提供更快的响应速度
- 优势:
- 本地部署,零网络延迟
- 数据隐私,敏感信息不出内网
- 成本更低,无需调用付费 API
典型架构
┌─────────────────┐
│ AI 编程助手 │
│ OpenClaw/Code │
└────────┬────────┘
│
▼
┌─────────────────┐
│ PI-LLM-Server │ ← 统一网关 (8090)
│ 网关服务 │
└────────┬────────┘
│
┌────┼────┬─────────┬──────────┬──────────┐
▼ ▼ ▼ ▼ ▼ ▼
┌────────┐ ┌─────┐ ┌────────┐ ┌────────┐ ┌──────────┐
│Embedding│ │ ASR │ │Reranker│ │ MinerU │ │pi-memory │
│ :8091 │ │:8092│ │ :8093 │ │ :8094 │ │ :9873 │
└────────┘ └─────┘ └────────┘ └────────┘ └──────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌─────────┐ ┌─────┐ ┌────────┐ ┌────────┐ ┌──────────┐
│Qwen3- │ │Qwen3│ │Qwen3- │ │MinerU │ │pi-memory │
│Embedding│ │-ASR │ │Reranker│ │VLM │ │Server │
└─────────┘ └─────┘ └────────┘ └────────┘ └──────────┘
项目结构
pi-llm-server/
├── pi_llm_server/ # 主包目录
│ ├── __init__.py
│ ├── __main__.py # python -m pi_llm_server 入口
│ ├── cli.py # 命令行工具(一站式启动)
│ ├── server.py # FastAPI 应用主服务
│ ├── config.py # 配置管理
│ ├── launcher/ # 子服务启动器
│ │ ├── embedding_server.py
│ │ ├── asr_server.py
│ │ ├── reranker_server.py
│ │ ├── service_manager.py # 服务管理器
│ │ ├── service_daemon.py # 服务守护进程(自动监控重启)
│ │ └── mineru_server.sh
│ ├── services/ # 服务实现
│ │ ├── embedding.py
│ │ ├── asr.py
│ │ ├── reranker.py
│ │ └── mineru.py
│ ├── clients/ # 子服务客户端
│ │ ├── embedding_client.py
│ │ ├── asr_client.py
│ │ ├── reranker_client.py
│ │ └── mineru_client.py
│ ├── utils/ # 工具函数
│ │ ├── logging.py
│ │ └── queue_manager.py
│ └── examples/ # 示例文件和配置
│ ├── __init__.py
│ ├── basic_usage.py # Python 客户端使用示例
│ ├── config.example.yaml # 配置文件示例
│ ├── install-service.sh # systemd 服务自动安装脚本
│ └── pi-llm-server.service.template # systemd 服务模板
├── README.md # 项目说明
├── CHANGELOG.md # 变更日志
├── pyproject.toml # 项目配置和依赖
└── setup.py # 安装脚本(已废弃,使用 pyproject.toml)
示例文件说明
| 文件 | 说明 |
|---|---|
examples/basic_usage.py |
Python 客户端调用示例,包含 Embedding、Reranker、ASR、PDF 解析等完整示例 |
examples/config.example.yaml |
配置文件模板,复制为 ~/.config/pi-llm-server/config.yaml 使用 |
examples/install-service.sh |
systemd 服务自动安装脚本,推荐方式使用此脚本安装服务 |
examples/pi-llm-server.service.template |
systemd 服务模板文件,供手动配置时参考 |
故障排查
常见问题
-
服务启动失败: 检查端口是否被占用,使用
netstat -tlnp | grep 8090查看 -
模型加载失败: 确认模型路径正确,检查
~/.cache/modelscope/hub/models/目录 -
GPU 显存不足: 调整
gpu_memory_utilization参数,降低显存使用率 -
CUDA 版本不匹配: 检查 PyTorch CUDA 版本与系统 CUDA 是否一致
日志位置
# 网关日志
~/.cache/pi-llm-server/logs/gateway.log
# 子服务日志
~/.cache/pi-llm-server/logs/<service>.log
# 守护进程日志
~/.cache/pi-llm-server/logs/daemon.log
# 查看最新日志
tail -f ~/.cache/pi-llm-server/logs/gateway.log
License
MIT License
Metadata
Release files for pi-llm-server 1.1.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pi_llm_server-1.1.9.tar.gz | 1.7 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pi_llm_server-1.1.9-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 3.4 MB
Release files / pi_llm_server-1.1.9.tar.gz
| Download URL | pi_llm_server-1.1.9.tar.gz |
|---|---|
| Size | 1.7 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cea262dd1963481d9e92a1169ebecdbb941fc4f80fcffcf39f97cd00e89268b7
|
|
BLAKE2b-256 checksum How to use checksums |
f17ae068216cee4d0fcc65f79d3d97b2b19bc4c89bcf59860bd5c6d5b331a1b0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.8.10
|
Release files / pi_llm_server-1.1.9-py3-none-any.whl
| Download URL | pi_llm_server-1.1.9-py3-none-any.whl |
|---|---|
| Size | 1.7 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
32127f9228601ae1340a47877aacbcd0ba414b979fff5948435160af2dddaaa2
|
|
BLAKE2b-256 checksum How to use checksums |
a7a776e1d8551bdbee95aa202e789cbbb706bd5b9d1227471aaec85f301fd290
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.8.10
|