结论
目前 RDK S100P 官方工具链尚未直接提供 LangChain 适配层,但可通过 封装 oellm_run 为 HTTP API 服务 实现兼容。核心思路是:用 Python 快速构建一个符合 OpenAI 格式的 API 服务,LangChain 可直接调用。
实现步骤
1. 封装 oellm_run 为 HTTP 服务(使用 FastAPI)
由于 oellm_run 是命令行工具,你需要编写一个 Python 脚本来启动它并处理请求。
关键点: oellm_run 默认是一次性运行(运行完就退出),为了高性能,建议将其修改为长驻服务模式(如果工具链支持)或者在 Python 中通过 stdin/stdout 与其交互。
这里提供一个基于 子进程调用 的简易实现(适合低频调用):
# app.py
from fastapi import FastAPI
from pydantic import BaseModel
import subprocess
import json
app = FastAPI()
class ChatRequest(BaseModel):
messages: list
model: str = "s100p-local"
@app.post("/v1/chat/completions")
async def chat(req: ChatRequest):
# 提取用户最后一条消息 (简易处理,实际需根据模板拼接历史)
prompt = req.messages[-1]["content"]
# 构造命令 (注意:需确认 oellm_run 是否支持 stdin 或 --prompt 参数)
# 如果不支持,可能需要通过临时文件或 pipe 传递
cmd = [
"./oellm_run",
"--hbm_path", "../../model/DeepSeek_R1_Distill_Qwen_7B_1024.hbm",
"--tokenizer_dir", "../../config/DeepSeek_R1_Distill_Qwen_7B_config/",
"--template_path", "../../config/DeepSeek_R1_Distill_Qwen_7B_config/DeepSeek_R1_Distill_Qwen_7B.jinja",
"--model_type", "1",
"--prompt", prompt # 假设支持,不支持则需改用 stdin
]
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
content = result.stdout
if result.returncode != 0:
content = f"Error: {result.stderr}"
except Exception as e:
content = str(e)
return {
"choices": [{
"message": {"role": "assistant", "content": content}
}]
}
2. 启动服务
在 RDK S100P 上安装依赖并启动:
# 安装依赖
pip install fastapi uvicorn
# 启动服务(监听 0.0.0.0:8000)
uvicorn app:app --host 0.0.0.0 --port 8000
3. LangChain 调用示例
在你的开发机(或同一网络下的其他设备)上:
from langchain_community.llms import OpenAI
# 指向 S100P 的 IP 地址
llm = OpenAI(
openai_api_base="http://<S100P_IP>:8000/v1",
model_name="s100p-local",
openai_api_key="not-needed" # 本地服务可忽略
)
response = llm.invoke("你好,请介绍下 RDK S100P")
print(response)
关键注意事项与优化建议
-
输入格式适配(重要)
- 需确认
oellm_run是否支持--prompt参数。如果不支持,你可能需要通过 stdin 传递输入,或者修改工具链源码使其支持交互式输入。 - 多轮对话处理:LangChain 会发送
messages列表,你需要根据.jinja模板的要求,将历史对话拼接到prompt中再传给模型。
- 需确认
-
性能优化(必须做)
- 模型预加载:上面的示例每次请求都启动一次
oellm_run,模型加载会非常慢(可能几十秒)。 - 正确做法:
- 如果官方支持 Server 模式(长驻进程),请优先使用该模式,并通过 Socket/HTTP 与其通信。
- 如果只能命令行运行,考虑使用 Python 的
subprocess.Popen保持进程常驻,通过stdin/stdout管道进行通信,避免重复加载模型。
- 模型预加载:上面的示例每次请求都启动一次
-
MCP 与 Tools 支持
- LangChain 的 Tools 功能依赖于模型能返回特定的格式(如 JSON 或特定标记)。
- 你需要在 Prompt 模板中明确指示模型输出格式,并在 API 层解析返回内容,将其转换为 LangChain 可识别的
ToolCall对象。
替代方案(推荐优先尝试)
如果官方后续提供 ONNX Runtime 或 Triton 部署支持,可直接通过以下路径集成,性能更好且更稳定:
- 将模型转换为 ONNX 格式(需确认 BPU 是否支持)。
- 使用 Triton Inference Server 部署,原生支持 LangChain 的
TritonLLM接口。
社区资源引导
- 相关讨论:RDK s100p 跑 LLM 大语言模型
- 工具链文档:LLM Toolchain
建议: 如果你成功实现了封装,欢迎将代码开源到社区,方便后续开发者复用!目前这是一个比较新的需求,社区可能还在探索中。