当前位置:   article > 正文

一起学大模型 - 动手写一写langchain调用本地大模型(1)_langchain使用本地大模型

langchain使用本地大模型


前言

langchain的手册里只有使用在线openai接口这一个例子,实际运用中我们大部分还是要用本地的大模型的。所以我们一起尝试写一写,练一练


一、如何替代掉openai呢

替掉openai的关键是根据我们所使用的模型的具体调用方式来实现 generate 方法。LangChain 框架为我们提供了一个通用接口,我们需要根据不同模型的特点和 API 来重写这个接口中的方法,以便能够正确调用本地模型并生成所需的输出。

先看具体步骤

  1. 定义模型类:创建一个继承自 LangChainBaseLLM 类,并根据所使用的本地模型重写 generate 方法。
  2. 加载模型和分词器:在模型类的初始化方法中加载你想要使用的本地模型和分词器。
  3. 实现生成方法:在 generate 方法中,处理输入文本并调用模型的生成函数,返回生成的文本。
  4. 构建管道:使用定义好的模型类和生成方法,构建从用户输入到输出的处理管道。

1. 定义模型类

我们以 GPT-2 为例,定义一个调用本地 GPT-2 模型的 LocalGPT2LLM 类:

import torch
from transformers import GPT2LMHeadModel, GPT2Tokenizer
from langchain.llms import BaseLLM

class LocalGPT2LLM(BaseLLM):
    def __init__(self, model_name='gpt2', device='cpu'):
        self.tokenizer = GPT2Tokenizer.from_pretrained(model_name)
        self.model = GPT2LMHeadModel.from_pretrained(model_name).to(device)
        self.device = device

    def generate(self, prompt, max_length=50, temperature=0.7):
        inputs = self.tokenizer(prompt, return_tensors='pt').to(self.device)
        with torch.no_grad():
            outputs = self.model.generate(
                inputs.input_ids,
                max_length=max_length,
                temperature=temperature,
                pad_token_id=self.tokenizer.eos_token_id
            )
        return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

2. 构建处理管道

创建一个简单的管道类,整合模型的调用过程:

class NLPipeline:
    def __init__(self, llm):
        self.llm = llm

    def process(self, user_input):
        response = self.llm.generate(user_input)
        return response
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
'
运行

3. 测试与应用

初始化模型和管道,并进行测试:

# 初始化本地模型
local_gpt2_llm = LocalGPT2LLM(device='cuda' if torch.cuda.is_available() else 'cpu')

# 创建 NLP 管道
pipeline = NLPipeline(local_gpt2_llm)

# 用户输入
user_input = "The quick brown fox jumps over the lazy dog."

# 处理用户输入并生成输出
output = pipeline.process(user_input)
print(f"Output: {output}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

4. 扩展支持其他模型

为了支持其他模型(例如 BERT 进行嵌入和 GPT-3 进行生成),可以类似地定义模型类并重写 generate 方法。这里我们以 BERT 嵌入和 GPT-3 生成的组合为例:

from transformers import BertModel, BertTokenizer
import openai

class BERTEmbedder:
    def __init__(self, model_name='bert-base-uncased'):
        self.tokenizer = BertTokenizer.from_pretrained(model_name)
        self.model = BertModel.from_pretrained(model_name)

    def embed(self, text):
        inputs = self.tokenizer(text, return_tensors='pt')
        with torch.no_grad():
            outputs = self.model(**inputs)
        return outputs.last_hidden_state.mean(dim=1).squeeze().numpy()

class GPT3LLM(BaseLLM):
    def __init__(self, temperature=0.7, max_tokens=150):
        self.temperature = temperature
        self.max_tokens = max_tokens

    def generate(self, prompt):
        response = openai.Completion.create(
            engine="text-davinci-003",
            prompt=prompt,
            temperature=self.temperature,
            max_tokens=self.max_tokens
        )
        return response.choices[0].text.strip()

# 创建和组合模型
bert_embedder = BERTEmbedder()
gpt3_llm = GPT3LLM()

# 定义组合的管道
class CombinedNLPipeline:
    def __init__(self, embedder, llm):
        self.embedder = embedder
        self.llm = llm

    def process(self, user_input):
        # 生成嵌入向量
        embedding = self.embedder.embed(user_input)
        prompt = f"User input embedding: {embedding}\nGenerate response:"
        # 使用 GPT-3 生成输出
        response = self.llm.generate(prompt)
        return response

# 创建组合管道
combined_pipeline = CombinedNLPipeline(bert_embedder, gpt3_llm)

# 测试输入
user_input = "The quick brown fox jumps over the lazy dog."
output = combined_pipeline.process(user_input)
print(f"Output: {output}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

5. 小结

通过这种方法,可以灵活地集成各种本地模型,并将其与 LangChain 框架结合,构建复杂的自然语言处理管道。根据不同的模型和需求,重写 generate 方法,实现多样化的处理和生成任务。

二、怎么用langchain自带的管道符

LangChain 提供了 LLMChain 类,可以更方便地将不同的模型和步骤组合在一起。下面是如何使用 LLMChain 来替代 CombinedNLPipeline,将 BERT 用于嵌入,GPT-3 用于生成的示例。

1. 安装必要的库

确保你已经安装了所需的库:

pip install transformers openai langchain
  • 1

2. 定义 BERT 嵌入和 GPT-3 生成模型类

首先,定义用于生成嵌入的 BERT 模型类和用于生成文本的 GPT-3 模型类:

from transformers import BertModel, BertTokenizer
import openai
import torch
from langchain.llms import BaseLLM

# 定义 BERT 嵌入模型类
class BERTEmbedder:
    def __init__(self, model_name='bert-base-uncased'):
        self.tokenizer = BertTokenizer.from_pretrained(model_name)
        self.model = BertModel.from_pretrained(model_name)

    def embed(self, text):
        inputs = self.tokenizer(text, return_tensors='pt')
        with torch.no_grad():
            outputs = self.model(**inputs)
        return outputs.last_hidden_state.mean(dim=1).squeeze().numpy()

# 定义 GPT-3 生成模型类
class GPT3LLM(BaseLLM):
    def __init__(self, temperature=0.7, max_tokens=150):
        self.temperature = temperature
        self.max_tokens = max_tokens

    def generate(self, prompt):
        response = openai.Completion.create(
            engine="text-davinci-003",
            prompt=prompt,
            temperature=self.temperature,
            max_tokens=self.max_tokens
        )
        return response.choices[0].text.strip()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

3. 使用 LangChain 的 LLMChain

接下来,使用 LangChain 的 LLMChain 类来替代手动定义的管道类。

from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.embeddings import Embeddings

# 定义一个模板,将 BERT 的嵌入作为 GPT-3 的输入
prompt_template = PromptTemplate(
    template="User input embedding: {embedding}\nGenerate response:",
    input_variables=["embedding"]
)

# 实现一个嵌入模型类,用于在 LLMChain 中使用
class EmbeddingsWrapper(Embeddings):
    def __init__(self, embedder):
        self.embedder = embedder

    def embed(self, text):
        return self.embedder.embed(text)

# 初始化 BERT 嵌入模型和 GPT-3 生成模型
bert_embedder = BERTEmbedder()
gpt3_llm = GPT3LLM()

# 包装 BERT 嵌入模型
embedding_wrapper = EmbeddingsWrapper(bert_embedder)

# 创建 LLMChain
llm_chain = LLMChain(
    prompt_template=prompt_template,
    llm=gpt3_llm,
    embeddings=embedding_wrapper
)

# 用户输入
user_input = "The quick brown fox jumps over the lazy dog."

# 处理用户输入并生成输出
embedding = bert_embedder.embed(user_input)
output = llm_chain.run({"embedding": embedding})
print(f"Output: {output}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

4. 解释

  • BERTEmbedder 类:用于生成 BERT 嵌入。
  • GPT3LLM 类:用于调用 GPT-3 生成文本。
  • PromptTemplate:定义了 GPT-3 的提示模板,包含 BERT 生成的嵌入。
  • EmbeddingsWrapper 类:用于将 BERT 嵌入模型包装为 LangChain 的嵌入接口。
  • LLMChain:将 BERT 嵌入模型和 GPT-3 生成模型组合在一起,形成一个完整的处理管道。

5. 使用注意事项

  • 输入变量:确保 PromptTemplate 中的 input_variables 与实际输入变量匹配。
  • 模型配置:根据需要调整 GPT-3 和 BERT 模型的配置,如 temperaturemax_tokens

通过这种方式,使用 LangChainLLMChain 类,可以更简洁地实现复杂的模型组合,简化代码结构,并提高可读性和维护性。


三、怎么才能用绝对地址引入本地模型呢

transformers 库支持从本地路径加载模型和分词器。只需要将 model_name 替换为模型和分词器所在的本地目录的绝对路径即可。

1. 使用本地模型路径的示例

假设你已经将 BERT 模型和分词器下载到本地目录 /path/to/local/bert-model,你可以这样进行修改:

from transformers import BertModel, BertTokenizer
import openai
import torch
from langchain.llms import BaseLLM

# 定义 BERT 嵌入模型类
class BERTEmbedder:
    def __init__(self, model_path='/path/to/local/bert-model'):
        self.tokenizer = BertTokenizer.from_pretrained(model_path)
        self.model = BertModel.from_pretrained(model_path)

    def embed(self, text):
        inputs = self.tokenizer(text, return_tensors='pt')
        with torch.no_grad():
            outputs = self.model(**inputs)
        return outputs.last_hidden_state.mean(dim=1).squeeze().numpy()

# 定义 GPT-3 生成模型类
class GPT3LLM(BaseLLM):
    def __init__(self, temperature=0.7, max_tokens=150):
        self.temperature = temperature
        self.max_tokens = max_tokens

    def generate(self, prompt):
        response = openai.Completion.create(
            engine="text-davinci-003",
            prompt=prompt,
            temperature=self.temperature,
            max_tokens=self.max_tokens
        )
        return response.choices[0].text.strip()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

2. 组合使用 LangChain 的 LLMChain

下面是如何使用 LangChain 的 LLMChain 类,结合本地的 BERT 模型和 GPT-3:

from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.embeddings import Embeddings

# 定义一个模板,将 BERT 的嵌入作为 GPT-3 的输入
prompt_template = PromptTemplate(
    template="User input embedding: {embedding}\nGenerate response:",
    input_variables=["embedding"]
)

# 实现一个嵌入模型类,用于在 LLMChain 中使用
class EmbeddingsWrapper(Embeddings):
    def __init__(self, embedder):
        self.embedder = embedder

    def embed(self, text):
        return self.embedder.embed(text)

# 初始化本地 BERT 嵌入模型和 GPT-3 生成模型
bert_embedder = BERTEmbedder(model_path='/path/to/local/bert-model')
gpt3_llm = GPT3LLM()

# 包装 BERT 嵌入模型
embedding_wrapper = EmbeddingsWrapper(bert_embedder)

# 创建 LLMChain
llm_chain = LLMChain(
    prompt_template=prompt_template,
    llm=gpt3_llm,
    embeddings=embedding_wrapper
)

# 用户输入
user_input = "The quick brown fox jumps over the lazy dog."

# 处理用户输入并生成输出
embedding = bert_embedder.embed(user_input)
output = llm_chain.run({"embedding": embedding})
print(f"Output: {output}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

3. 解释

  • model_path:将模型路径从预训练模型名称替换为本地目录的绝对路径。
  • BERTEmbedder 类:加载本地路径中的 BERT 模型和分词器。
  • LLMChain:与之前相同,定义一个 LangChain 的 LLMChain,用于将 BERT 嵌入和 GPT-3 生成结合起来。

通过这种方式,你可以方便地使用本地存储的模型文件,避免了每次使用时都需要从互联网下载模型文件。这样不仅可以节省时间,还可以在没有互联网连接的环境中使用模型。

总结

以上我们用三个章节介绍了如何调用本地模型,如何使用langchain自带的管道方法,以及如何从绝对地址来调用模型。 大家可以清晰的在各段代码里看到改变,可以尝试自己使用自己的方法。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/821644
推荐阅读
相关标签
  

闽ICP备14008679号