赞
踩
langchain的手册里只有使用在线openai接口这一个例子,实际运用中我们大部分还是要用本地的大模型的。所以我们一起尝试写一写,练一练
替掉openai的关键是根据我们所使用的模型的具体调用方式来实现 generate
方法。LangChain
框架为我们提供了一个通用接口,我们需要根据不同模型的特点和 API 来重写这个接口中的方法,以便能够正确调用本地模型并生成所需的输出。
先看具体步骤
- 定义模型类:创建一个继承自
LangChain
的BaseLLM
类,并根据所使用的本地模型重写generate
方法。- 加载模型和分词器:在模型类的初始化方法中加载你想要使用的本地模型和分词器。
- 实现生成方法:在
generate
方法中,处理输入文本并调用模型的生成函数,返回生成的文本。- 构建管道:使用定义好的模型类和生成方法,构建从用户输入到输出的处理管道。
我们以 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)
创建一个简单的管道类,整合模型的调用过程:
class NLPipeline:
def __init__(self, llm):
self.llm = llm
def process(self, user_input):
response = self.llm.generate(user_input)
return response
初始化模型和管道,并进行测试:
# 初始化本地模型
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}")
为了支持其他模型(例如 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}")
通过这种方法,可以灵活地集成各种本地模型,并将其与 LangChain 框架结合,构建复杂的自然语言处理管道。根据不同的模型和需求,重写 generate
方法,实现多样化的处理和生成任务。
LangChain
提供了 LLMChain
类,可以更方便地将不同的模型和步骤组合在一起。下面是如何使用 LLMChain
来替代 CombinedNLPipeline
,将 BERT 用于嵌入,GPT-3 用于生成的示例。
确保你已经安装了所需的库:
pip install transformers openai langchain
首先,定义用于生成嵌入的 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()
接下来,使用 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}")
PromptTemplate
中的 input_variables
与实际输入变量匹配。temperature
和 max_tokens
。通过这种方式,使用 LangChain
的 LLMChain
类,可以更简洁地实现复杂的模型组合,简化代码结构,并提高可读性和维护性。
transformers
库支持从本地路径加载模型和分词器。只需要将 model_name
替换为模型和分词器所在的本地目录的绝对路径即可。
假设你已经将 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()
下面是如何使用 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}")
LLMChain
,用于将 BERT 嵌入和 GPT-3 生成结合起来。通过这种方式,你可以方便地使用本地存储的模型文件,避免了每次使用时都需要从互联网下载模型文件。这样不仅可以节省时间,还可以在没有互联网连接的环境中使用模型。
以上我们用三个章节介绍了如何调用本地模型,如何使用langchain自带的管道方法,以及如何从绝对地址来调用模型。 大家可以清晰的在各段代码里看到改变,可以尝试自己使用自己的方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。