《从零开始DeepSeek R1搭建本地知识库问答系统》六:关于聊天模型 API Key 的使用与调用 Embedding 模型

前言

上两章节我们实现了本地知识库问答系统的前后端分离开发,还没看的同学请前往观看:

《从零开始DeepSeek R1搭建本地知识库问答系统》四:FastApi 框架搭建本地知识库问答Web Server端

《从零开始DeepSeek R1搭建本地知识库问答系统》五:实现问答系统前端 UI 框架,基于 vue3 + typescript + ElementPlus

在评论区有同学提问了不使用本地部署模型,能否使用聊天模型的 API key。这个问题问得好,我一下子来了兴致嘿嘿。单独说说如何在 LangChain 中调用聊天模型 API Key 和 Embedding 模型。

在此之前我先再聊一下 Ollama 服务,因为近期有报道出 Ollama 具有安全风险,默认端口开放 11434 端口且无任何鉴权机制,该服务直接暴露在公网环境。别有用心的人会直接访问,极易引发网络和数据安全事件。

规避风险的一种是修改端口,添加防火墙。

我的项目中,有这两个 LangChain 调用 Ollama 里的模型的代码:

python 复制代码
# llm 模型
llm = ChatOllama(
    model="deepseek-r1:7b",
    temperature=0.3,
    streaming=True,
    callbacks=[StreamingStdOutCallbackHandler()],
)

# embedding 模型
embedding = OllamaEmbeddings(model="deepseek-r1:7b")

有的同学会有疑问为啥没有指定模型的路径,就能启动模型,这是因为 Ollama 默认开机启动服务的(这也是暴露风险之一),不需要我们手动启动服务,ChatOllama()OllamaEmbeddings() 会默认使用 http://localhost:11434 发送请求来连接 Ollama,只要 model 参数与 Ollama 注册的模型名称相同,即可找到相对应的模型地址并调用。

如果修改了 Ollama 服务的端口如 12345,请在项目中添加 base_url 参数覆盖默认值,不然会找不到报错:

python 复制代码
# llm 模型
llm = ChatOllama(
    base_url="http://localhost:12345"
    model="deepseek-r1:7b",
    temperature=0.3,
    streaming=True,
    callbacks=[StreamingStdOutCallbackHandler()],
)

# embedding 模型
embedding = OllamaEmbeddings(base_url="http://localhost:12345", model="deepseek-r1:7b")

LangChain 文档解读

众所周知,LangChain 是一个用于开发由大型语言模型提供支持的应用程序的框架 (LLMs)。其中整合封装提供了非常非常多的工具库,以至于小萌新刚开始看 LangChain 文档的时候是一头雾水,一脸懵逼。

其实如果你初步了解 RAG 的流程,你就会看懂 LangChain 一大半的文档了:

文档的导航目录,Components 目录下其实就是构建一个完整 Agents 应用的教程。RAG 是其中的一部分。

里面的翻译:猎犬,是翻译错误。其实正确翻译是:检索器。

但我估计有不少人没有点过这里:

这里面 LangChain 集成了很多主流的聊天模型和 Embedding 模型。

一、聊天模型 API Key 的使用

方式一:LangChain 集成

首先打开 LangCHain 聊天模型。然后 Ctrl + F 搜索你需要调用的聊天模型,例如,我这里搜索 DeepSeek 的:

点击进去就可以看到相关的调用 DeepSeek API Key 的文档,如下保存 API Key:

DEEPSEEK_API_KEY 这个名字不要乱改。API Key 写在 getpass.getpass() 函数里。

python 复制代码
import getpass
import os

# 将 API Key 添加到环境变量中
if not os.getenv("DEEPSEEK_API_KEY"):
    os.environ["DEEPSEEK_API_KEY"] = getpass.getpass("xxxx-xxxx-xxxx-xxxx")

接着安装 langchain-deepseek

bash 复制代码
pip install -U langchain-deepseek

就可以调用聊天模型,langchain-deepseek 包会自动查找你刚才在环境变量中设置的 "DEEPSEEK_API_KEY"

python 复制代码
from langchain_deepseek import ChatDeepSeek

llm = ChatDeepSeek(
    model="deepseek-chat",
    temperature=0,
    max_tokens=None,
    timeout=None,
    max_retries=2,
    # 如果不想把 API key 保存到环境变量里,也可以在这里参数写 api_key
    # api_key="xxxx-xxxx-xxxx-xxxx"
    
    # 其它参数...
)

方式二:OpenAI 工具类

可能有的同学会问,我想要的聊天模型,在 LangChain 聊天模型 里找不到怎么办?

我不想用 LangChain 集成,好麻烦,我就想根据人家聊天模型的文档里弄,该怎么搞?

有的有的,包有的。

一般来说,国内的聊天模型,基本都会有 OpenAI 的方式来接入。

例如,我在 DeepSeek 官方接口文档 API,可以找到这部分代码:

不过,我们不用 openai.OpenAI(),而是使用 LangChain 的 OpenAI 工具类,先安装依赖:

bash 复制代码
pip install langchain-openai

接着写一下代码,用到 OpenAI 的库:

python 复制代码
from langchain_openai import ChatOpenAI

client = ChatOpenAI(
    model="deepseek-reasoner",
    api_key="xxxx-xxxx-xxxx-xxxx",
    base_url="https://api.deepseek.com/v1",
)

# 下面的代码不用管,后面会利用 LangChain 管道来输出文本,当然,除非你想脱离 LangChain 框架。
# response = client.chat.completions.create(
#     model="deepseek-chat",
#     messages=[
#         {"role": "system", "content": "You are a helpful assistant"},
#         {"role": "user", "content": "Hello"},
#     ],
#     stream=False,
# )

# print(response.choices[0].message.content)

至此,你的聊天模型 API Key 就已经集成进来了。

调用 DeepSeek API 的问题

我使用 LangChain 调用 deepseek-reasoner API 的时候,返回的内容本应该会有 think 标签和 think 里的内容。但是我用的时候,think 内容是持续的空字符串,我没有找到问题源头,不知道是因为 LangChain 没有正确获取到思考的内容导致 think 里的内容解析成空字符串了,还是官方 API 接口返回的 think 内容就是持续的空字符串。

有同学知道原因的话,可以在评论区留言。

我猜测是因为 deepseek-reasoner API 接口,think 内容和正文内容使用两个参数分开了,导致 LangChain 管道只获取了正文的内容,具体如何获取到 think 内容,我还没有找到解决的方式。

二、Embedding 嵌入模型

Embedding 模型其实调用方式和聊天模型一样,也需要有工具库来驱动,或者需要部署。

但是 Embedding 模型和聊天模型不要混淆在一起。其作用侧重点不一样,聊天模型用于生成任务,而 RAG 需要的 Embedding 模型是经过预训练或微调后,专门为文本向量化,针对语义相似性优化和增强检索功能的模型。

虽然聊天模型也可以作为 Embedding 模型来使用,但效率会有折扣,在检索任务中表现会稍差些。

目前我的项目中为了偷懒直接用聊天模型作为 Embedding 模型来使用了:

python 复制代码
vector_store = Chroma(
    persist_directory=persist_dir,
    collection_name=COLLECTION_NAME,
    # 利用 LangChain 的 OllamaEmbeddings 工具类将 deepseek-r1:7b 模型作为 Embedding 模型
    embedding_function=OllamaEmbeddings(model="deepseek-r1:7b"),
)

注意不要想着调用 chat 模型 API Key 来当 Embedding 模型使用,其接口参数和返回数据不一样!

通常来说,Embedding 模型也不是越大越好用,有的几百 MB 的模型照样吊打十几 GB 的模型,我们选用 Embedding 模型,控制在 2G 大小以内,太大会占用 LLM 模型的资源,毕竟不是人人都有 A100。

有些 Embedding 模型也提供了 API Key 的方式,LangChain 都有对应的 embedding 调用库。

我更加推荐将 Embedding 模型下载下来,本地使用。毕竟调用 Embedding 模型占用资源(显存)不是特别大,基本上都够用。

1. Embedding 模型调用工具库

常用的 Embedding 模型工具库有以下几种:

  1. HuggingFace Transformers:使用方式相对底层,是 LLM 模型通用的加载框架。支持加载多种预训练模型,也适用于文本向量化、微调和自定义任务。提供灵活的API,支持模型本地加载或在线调用。兼容多语言模型(如BGE-M3、GTE-Qwen等)。直接调用AutoModelAutoTokenizer生成嵌入向量。

  2. Sentence-Transformers:同属于 HuggingFace 下的 Python 库,是 Transformers 的加工升级版,使用方式特别简单。专注于生成高质量的句子或段落级嵌入向量,优化语义相似度计算。内置池化层,简化句子嵌入的生成流程。支持多语言模型(如 BGE 系列、Conan-Embedding 等)。通过SentenceTransformer class 快速生成归一化向量,支持语义搜索和相似度计算。

  3. FlagEmbedding:专注于稠密向量生成和外部知识融合的库。支持长文本处理(如BGE-M3模型支持8K Token输入)。结合知识图谱等外部数据增强语义表示。适用于复杂检索场景(如RAG系统)。

  4. Ollama:没错,Ollama 也支持 Embedding 模型部署,只需要在官网 Embedding models 想要的 Embedding 模型,命令行:ollama pull 的方式注册到 Ollama 中即可,部署方式特别简单。

Embedding 模型都会有相应的文档,文档里都会提到如何用哪些工具库。

这里可以看 Embedding 模型的排行:MTEB Leaderboard - a Hugging Face Space by mteb

2. 关于 FlagEmbedding 工具库

由于 FlagEmbedding 工具库是近期新出的,LangChain 还没有集成进来,如果你下载了只能使用 FlagEmbedding 的 Embedding 模型,需要 自定义嵌入模型类实现 。不过不用担心,大部分热门的 Embedding 模型都支持多种工具库启动。

下面我会提供自定义嵌入接口实现方法。

3. Embedding 模型下载

  1. Models - Hugging Face 中,点击左侧的 Libraries 标签页,然后选择 Transformers 标签或 sentence-transformers 标签。
  1. 模型库首页 · 魔搭社区 中,点击左侧的"框架"标签,然后选择 Transformers 标签或 sentence-transformers 标签。。
  1. FlagEmbedding Github 中有提到模型选择。
  1. Ollama,中选择 Embedding 下载。

4. langchain_chroma 调用 embedding 模型

Chroma 向量数据库需要用到 embedding 模型,一次是对文本向量化存入数据库时,另一次是从数据库检索数据时。

LangChain 集成 Chroma 向量数据库,通过 embedding_function 来调用 embedding 模型,代码如下:

python 复制代码
from langchain_chroma import Chroma

vector_store = Chroma(
    persist_directory="/home/ly/Project/fileStorage",
    collection_name="documents_qa",
    # embedding_function
    embedding_function= xxx,
)

1)API Key

API Key 的调用方式我还没使用过,毕竟要钱。如果有需求的同学,可以看看 LangChain 文档的百川文本嵌入模型 使用方式:Baichuan Text Embeddings | 🦜️🔗 LangChain

python 复制代码
from langchain_community.embeddings import BaichuanTextEmbeddings

# embedding 模型
embeddings = BaichuanTextEmbeddings(baichuan_api_key="sk-*")

# 向量数据库
vector_store = Chroma(
    persist_directory="/home/ly/Project/fileStorage",
    collection_name="documents_qa",
    # embedding_function
    embedding_function=embeddings,
)

注意,我没有尝试过是否能成功运行,如果有问题,请自行解决233333。

或者单独看百川文本嵌入模型的官方接口文档:百川文本嵌入模型。这种接口文档需要重写自定义嵌入模型类实现

2)下载模型到本地调用

这里我以 BAAI/bge-base-zh-v1.5 · Hugging Face 举例,下载模型到 home/ly/Project/Models/Embedding 目录。

从模型介绍中,bge-base-zh-v1.5 模型同时支持 HuggingFace Transformers、Sentence-Transformers 和 FlagEmbedding 三种方式。

方式一:LangChain 专门提供的 bge 工具库

bge-base-zh-v1.5 模型是是由北京智源人工智能研究院提出的 embedding 模型。LangChain 对北京人工智能研究院 (BAAI) 旗下的所有 BGE 模型提供了对应的调用工具库:HuggingFaceBgeEmbeddings 类

pip 下载依赖库:

bash 复制代码
pip install sentence_transformers

使用方式:

python 复制代码
from langchain_community.embeddings import HuggingFaceBgeEmbeddings

# embedding 模型
embeddings = HuggingFaceBgeEmbeddings(
    model_name="/home/ly/Project/Models/Embedding/bge-base-zh-v1.5",
)

# 向量数据库
vector_store = Chroma(
    persist_directory="/home/ly/Project/fileStorage",
    collection_name="documents_qa",
    # embedding_function
    embedding_function=embeddings,
)
方式二:HuggingFace Transformers 和 Sentence-Transformers

LangChain 有对应的封装好的工具类:HuggingFaceEmbeddings 类

pip 安装依赖库:

bash 复制代码
pip install langchain-huggingface

使用方式:

python 复制代码
from langchain_huggingface import HuggingFaceEmbeddings

# embedding 模型
embeddings = HuggingFaceEmbeddings(model_name="/home/ly/Project/Models/Embedding/bge-base-zh-v1.5")

# 向量数据库
vector_store = Chroma(
    persist_directory="/home/ly/Project/fileStorage",
    collection_name="documents_qa",
    # embedding_function
    embedding_function=embeddings,
)
方式三:自定义 embedding 模型类

由于 FlagEmbedding 工具库是近期新出的,LangChain 还没有集成进来,所以使用自定义嵌入模型类实现

pip 安装依赖库:

bash 复制代码
pip install -U FlagEmbedding

注意:安装 FlagEmbedding 前提需要安装 Pytorch,请根据自己的电脑cuda版本安装。PyTorch 下载地址。

使用方式:

python 复制代码
from typing import List
from FlagEmbedding import FlagModel
from langchain_core.embeddings import Embeddings

class CustomEmbeddings(Embeddings):
    """自定义 Embedding 接口实现"""

    def __init__(self):
        # 使用 FlagEmbedding 库下的 FlagModel
        model = FlagModel(
            model_name_or_path="/home/ly/Project/Models/Embedding/bge-base-zh-v1.5",
        )
        self.model = model

    def embed_documents(self, texts: List[str]) -> List[List[float]]:
        """Embed search docs."""

        embeddings = [self.model.encode(x) for x in texts]
        return embeddings

    def embed_query(self, text: str) -> List[float]:
        """Embed query text."""
        return self.embed_documents([text])[0]


# 向量数据库
vector_store = Chroma(
    persist_directory="/home/ly/Project/fileStorage",
    collection_name="documents_qa",
    # embedding_function
    embedding_function=CustomEmbeddings(),
)

如果你使用的嵌入模型在 LangChain 里找不到对应的工具类调用,都需要使用方式三来重写自定义嵌入模型类实现

5. Ollama 下载 embedding 模型

这里以 nomic-embed-text 为例:

提前已经按照 《从零开始DeepSeek R1搭建本地知识库问答系统》二:Ollama 部署 DeepSeek R1 蒸馏模型及Api测试 文章里,安装了 Ollama 服务。

打开 Ubuntu 终端,切换 r1 环境,输入以下代码:

bash 复制代码
ollama pull nomic-embed-text

ollama 会自动下载该模型到默认目录中,与聊天大模型的目录一致。

目录路径:/usr/share/ollama/.ollama/models

使用方式:

python 复制代码
from langchain_ollama import OllamaEmbeddings

# embedding 模型
embeddings = OllamaEmbeddings(model="nomic-embed-text")

# 向量数据库
vector_store = Chroma(
    persist_directory="/home/ly/Project/fileStorage",
    collection_name="documents_qa",
    # embedding_function
    embedding_function=CustomEmbeddings(),
)

三、在本项目中实现

所有的实现方式,我都写在了,/app/core/base.py 下:

csharp 复制代码
app                   
    ├── core         
    │   ├── base.py   # LangChan 常量配置

Github 地址: YuiGod/py-doc-qa-deepseek-server

结语

本章实现了聊天模型和 Embedding 模型调用的几种方式,希望对有需求的同学能提供到一些帮助。

最近在忙于投简历,感觉天都塌了 TvT。

相关推荐
BirdMan9811 分钟前
Flask实现分页的三种方法
数据库·python·flask
魔乐社区24 分钟前
基于Atlas 800I A2的RAG端到端实践
人工智能·深度学习·大模型·deepseek
计算机小混子31 分钟前
vscode python相对路径的问题
ide·vscode·python
A__tao1 小时前
在线 SQL 转 SQLAlchemy:一键生成 Python 数据模型
python·sql·oracle
好看资源平台1 小时前
加密算法逆向与HOOK技术实战
开发语言·python
胡耀超2 小时前
Xinference大模型配置介绍并通过git-lfs、hf-mirror安装
人工智能·git·python·大模型·llm·xinference
冷琴19962 小时前
基于python+django+vue.js开发的停车管理系统运行-期末作业
vue.js·python·django
Honeysea_702 小时前
常用的Python库
开发语言·python·机器学习·计算机视觉·ai·自然语言处理
编程梦想记2 小时前
Python在数据处理中的应用:从入门到精通
开发语言·python·信息可视化