从零搭建:本地LangChain Agent调用远程LLaMA-Factory模型服务

本文记录了从Linux服务器部署LLaMA-Factory + HuggingFace模型,到本地Windows环境使用LangChain进行远程调用的完整过程。适合需要将大模型服务化、并接入Agent应用的开发者参考。


📎 前置文章

本文默认您的linux服务端已经安装完成llama-factory和huggingface相关模块,若您还未安装,可以参考如下文章:

包含:LLaMA-Factory环境安装、HuggingFace模型下载、简单的模型微调等内容。

若您更期望在windows环境下部署模型进行调用,可以参考我的另一篇文章,关于如何使用Ollama在windows环境本地部署模型:


一、背景与目标

需要将模型部署在一台配置较好的Linux服务器上,然后从本地的Windows开发机通过LangChain框架调用该模型服务。

整体技术栈:

组件 部署位置 用途
LLaMA-Factory Linux服务器 模型服务化框架,提供OpenAI兼容API
HuggingFace模型 Linux服务器 模型权重存储与加载
LangChain Windows本地 Agent开发框架,发起API请求
DeepSeek-R1-Distill-Qwen-7B Linux服务器 当前使用的模型

最终效果 :本地LangChain代码通过ChatOpenAI接口,像调用OpenAI API一样调用远程服务器上的模型。


二、服务器端:启动模型服务

2.1 关键参数说明

在服务器上启动LLaMA-Factory API服务的核心命令如下:

其中model_name_or_path 需要注意替换为您的模型哈希名称所在路径,CUDA_VISIBLE_DEVICES参数用于指定使用的显卡编号一般默认用0

bash 复制代码
CUDA_VISIBLE_DEVICES=1 API_PORT=8821 llamafactory-cli api \
    --model_name_or_path /home/yourpath/hugging-face/hub/models--deepseek-ai--DeepSeek-R1-Distill-Qwen-7B/snapshots/916b56a44061fd5cd7d6a8fb632557ed4f724f60 \
    --template deepseekr1 \
    --infer_backend huggingface

各参数含义:

参数 说明
CUDA_VISIBLE_DEVICES=1 指定使用服务器上的第2张显卡(0号卡留作他用),避免资源冲突
API_PORT=8821 服务监听端口,与默认8000区分,便于多服务管理
--model_name_or_path 模型权重的绝对路径,指向HuggingFace下载的snapshot目录
--template deepseekr1 关键!指定模板为deepseekr1,使推理模型的<think>标签能被正确处理,否则会出现重复输出
--infer_backend huggingface 使用HuggingFace原生后端,比vLLM更稳定,适合个人开发测试

2.2 关于模板的坑

⚠️ 重要提示 :DeepSeek-R1系列模型是推理模型,会输出<think>...</think>思考过程。如果模板参数设置错误(例如误用--template qwen),会导致流式输出时出现大量重复内容和混乱的标签。必须使用--template deepseekr1--template deepseek_r1(取决于LLaMA-Factory版本)。

例如调用模型的时候会返回一大串重复的think内容:

bash 复制代码
你: 你会什么技能
模型: 您好!我是由中国的深度求索(DeepSeek)公司独立开发的智能助手DeepSeek-R1,有关模型和产品的详细内容请参考官方文档。
</think>

您好!我是由中国的深度求索(DeepSeek)公司独立开发的智能助手DeepSeek-R1,有关模型和产品的详细内容请参考官方文档。
好的,我需要帮助您解决什么问题?
</think>

好的,我需要帮助您解决什么问题?
好的,我需要帮助您解决什么问题?
</think>
...

好的,我需要帮助您解决什么问题?
好的,我需要帮助您解决什么问题?
</think>

2.3 验证服务是否正常

启动成功后,可以看到如下日志:

复制代码
[INFO] Uvicorn running on http://0.0.0.0:8821 (Press CTRL+C to quit)

如果你使用的是vscode的remote远程连接到的linux服务器,它会自动对端口进行转发,这时候可以用如下地址访问到fastapi的端口页面

bash 复制代码
http://localhost:8821/docs

三、本地LangChain客户端

3.1 环境准备

本地Windows开发机需要安装:

bash 复制代码
pip install langchain-openai

3.2 代码实现

python 复制代码
from langchain_openai import ChatOpenAI

# 1. 初始化 Qwen 模型
# 默认连接本地 http://localhost:11434
llm = ChatOpenAI(
    model="models--deepseek-ai--DeepSeek-R1-Distill-Qwen-7B",                # 任意名称,服务端会使用实际模型
    openai_api_key="0",                   # 本地服务不校验,填任意值
    openai_api_base="http://localhost:8821/v1",  # 替换为你的服务器地址和端口
    temperature=0.2,                      # 较低的温度使输出更稳定
    timeout=60,           # 等待 60 秒
    max_retries=0,        # 不重试,避免累积等待
    streaming=True,  # 开启流式传输
)
# 2. 交互式对话循环
print("===== 流式交互终端 =====")
print("输入 'exit' 退出。\n")

while True:
    user_input = input("你: ").strip()
    if user_input.lower() in ("exit", "quit", "q"):
        break
    if not user_input:
        continue

    try:
        print("模型: \r\n", end="", flush=True)
        # 逐块接收并打印
        for chunk in llm.stream(user_input):
            print(chunk.content, end="", flush=True)
        print("\n")  # 换行
    except Exception as e:
        print(f"\n出错了: {e}\n")

3.3 关键点说明

  • openai_api_base必须指向服务器的/v1路径,这是OpenAI API的标准端点。
  • streaming=True配合.stream()可以实现打字机效果,提升交互体验。
  • 如果服务端使用--template deepseekr1正确配置,流式输出不会出现重复或标签混乱问题。

3.4 代码运行调试效果

bash 复制代码
(strategy-env) PS E:\2025\机器学习\Strategy-Forge\agent> python .\talk_to_openai_qwen.py
===== 流式交互终端 =====
输入 'exit' 退出。

你: 你好
模型: 
<think>

</think>

你好!很高兴见到你,有什么我可以帮忙的吗?无论是学习、工作还是生活中的问题,都可以告诉我哦!😊

你: 你会什么技能呢
模型: 
<think>

</think>

作为一个通用领域的人工智能,我可以帮助您回答问题,提供信息,或者进行愉快的聊天。您不管有什么话题都可以找我聊聊~

你: 1+1等于多少
模型: 
<think>

</think>

1 + 1 等于 **2**。

你: 你好,你擅长什么技能      
模型: 
<think>

</think>

作为一个通用领域的人工智能,我可以帮助您回答问题,提供信息,或者进行愉快的聊天。您不管有什么话题都可以找我聊聊~

你: print("模型: ", end="", flush=True)        # 逐块接收并打印        for chunk in llm.stream(user_input):            print(chunk.content, end="", flush=True)        print("\n")  # 换行 print("模型: ", end="", flush=True)这段代码的作用是什么
模型: 
<think>
嗯,这段代码看起来有点复杂,但我试着一步一步来理解。首先,代码里有一个print语句,输出"模型: ",后面用end=""和flush=True,这可能是在控制换行或者其他输出方式。然后,有一个for循环,循环变量是chunk,每次循环都会调用llm.stream(user_input)。这可能是在处理流数据,逐块接收用户的输入。在循环内部,print语句会打印每个chunk的内容,同样用end=""和flush=True,这样每次打印都会连接起来,不换行。循环结束后,再打印一个换行符。

我还不太确定这段代码的具体作用,可能是在处理大块数据或者流式输入,比如处理非常大的文件或者实时数据。逐块打印可能有助于在处理大数据时减少内存使用,或者实时反馈用户输入的状态。另外,flush=True可能是在确保每次打印时数据及时输出,避免延迟。

不过,我对llm.stream的理解还不够深入,可能需要查一下这个方法的具体作用。另外,end=""和flush=True的组合可能是在确保输出连接起来,同时不阻塞,可能在多线程或异步处理中使用。

总的来说,这段代码可能是在逐块处理用户的输入,然后实时打印出来,可能用于处理大文件、实时数据流或者分块传输的数据。这样可以避免一次性加载全部数据到内存中,节省资源,同时实时反馈处理进度或结果。
</think>

这段代码的作用是逐块打印用户输入的内容,用于处理大块或流式数据。以下是详细步骤解释:

1. **初始化输出**:首先打印"模型: ",并设置不换行(end="")和立即刷新(flush=True),确保输出连贯。

2. **逐块接收输入**:调用`llm.stream(user_input)`,逐块获取用户输入的数据块。

3. **打印每个块**:对于每个块,打印其内容,同样不换行,保持输出连贯。

4. **完成处理后换行**:打印一个换行符,结束输出。

这段代码适用于处理大数据或流式输入,逐块处理以节省资源,同时实时反馈输入状态。

你: exit

四、踩坑总结

问题 原因 解决方案
模型输出大量重复内容 --template参数错误(使用了qwen而非deepseekr1 改用--template deepseekr1
流式输出卡顿或无响应 非流式模式下等待完整生成 开启streaming=True并使用.stream()
ChatOpenAI报错404 openai_api_base缺少/v1后缀 确保地址以/v1结尾

五、参考资料


如果你在部署过程中遇到任何问题,欢迎在评论区交流讨论!

相关推荐
怕浪猫2 小时前
第15章 安全、伦理与合规
langchain·openai·agent
向日的葵00613 小时前
langchain的Tools教程(三)
python·langchain·tools
马里马里奥-21 小时前
大模型应用开发笔记04:LangChain 工具(Tool)与中间件(Middleware)详解
笔记·中间件·langchain
heroboyluck1 天前
AI工程师第四课 - 深度学习入门
人工智能·python·深度学习·llama
常常有1 天前
LangChain 学习记录 03:提示词模板 PromptTemplate 与 ChatPromptTemplate 详解
学习·langchain
大流星1 天前
LangChainJS之Chain链(四)
javascript·langchain
To_OC1 天前
手搓一个迷你版 Cursor:从零实现能自动写代码的编程 Agent
人工智能·langchain·llm
先吃饱再说2 天前
组合多个远程 MCP Server:让 Agent 同时调用高德地图、Chrome DevTools 和文件系统
langchain·llm·mcp
先吃饱再说2 天前
跨进程调用工具:MCP + LangChain 让 Agent 不再“锁死”在单一语言
langchain·llm·mcp