【本文正在参加金石计划附加挑战赛——第一期命题】
前言
在上一篇文章, 我曾提到过OpenAI无法在国内充值, 所以我转而寻找免费的开源模型, 通过比较我在Hugging Face(开源的模型库网站)找到微软的 DialoGPT 模型, 即microsoft/DialoGPT-medium模型. 通过对前面代码反复修改, 最终版如下所示:
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
# 加载模型和分词器
tokenizer = AutoTokenizer.from_pretrained("microsoft/DialoGPT-medium")
model = AutoModelForCausalLM.from_pretrained("microsoft/DialoGPT-medium")
# 初始化对话历史记录
history = torch.tensor([], dtype=torch.long) # 将历史记录初始化为空长整型张量
MAX_LENGTH = 1024 # 模型的最大长度(标记数量)
def chat_with_dialoGPT(user_input, history):
"""
处理与 DialoGPT 的对话。
"""
# 拼接用户输入和历史对话,作为模型的输入
new_user_input_ids = tokenizer.encode(user_input + tokenizer.eos_token, return_tensors='pt').long()
# 如果有历史对话,将其加入模型的输入
if history.size(0) > 0:
bot_input_ids = torch.cat([history, new_user_input_ids], dim=-1)
else:
bot_input_ids = new_user_input_ids
# 如果输入长度超过最大长度,截断最早的部分
if bot_input_ids.size(-1) > MAX_LENGTH:
bot_input_ids = bot_input_ids[:, -MAX_LENGTH:]
# 创建 attention_mask(1表示有效标记,0表示填充标记)
attention_mask = torch.ones(bot_input_ids.shape, dtype=torch.long)
# 生成响应
bot_output = model.generate(
bot_input_ids,
attention_mask=attention_mask, # 明确设置 attention_mask
max_length=MAX_LENGTH,
pad_token_id=tokenizer.eos_token_id,
do_sample=True,
top_k=50
)
# 解码模型生成的响应
bot_response = tokenizer.decode(bot_output[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
# 更新历史记录,保持上下文
history = torch.cat([history, new_user_input_ids, bot_output], dim=-1)
return bot_response, history
if __name__ == "__main__":
print("Chatbot: 你好!有什么问题我可以帮你解答吗?")
while True:
# 获取用户输入
user_input = input("你: ")
if user_input.lower() == "exit":
print("Chatbot: 再见!期待下次和你聊天!")
break
# 获取机器人的回答
response, history = chat_with_dialoGPT(user_input, history)
print(f"Chatbot: {response}")
但是上面代码仍然存在问题, 即提问的问题不能超过4个, 否则的话, 机器人回答则是一片空白, 这不是我想要的.
无意中, 我又发现了一篇文章, 惊喜地发现能通过302.ai间接地在OpenAI上充值.
当然, 302.ai会收取中间费用, 但相比较, 在5美元的基础上, 只多了十多元人民币, 这不就是一顿饭钱吗? 所以, 我兴冲冲地充了最低值, 准备拿LangChain练练手.
正文
设置openai_api_key
302.ai充值成功后, 它提供的openai_api_key便可以拿来使用了.
你可以全局设置openai_api_key
import os
API_SECRET_KEY = "sk-XXX" #302.AI后台-使用API-API Keys 生成的API KEY
BASE_URL = "https://api.302.ai/v1/chat/completions"; #302.AI的base-url
os.environ["OPENAI_API_KEY"] = API_SECRET_KEY
os.environ["OPENAI_BASE_URL"] = BASE_URL
或者在代码里引入
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model_name='gpt-4o-mini',
openai_api_key='sk-XXX', #302.AI后台-使用API-API Keys 生成的API KEY
openai_api_base='https://api.302.ai/v1/chat/completions',
)
搭建对话机器人
在搭建对话机器人的过程中, 我遇到一些问题, 以下是部分问题, 以及对应的解决方法
Invalid input type <class 'dict'>
报错代码
...
response = llm([{"role": "user", "content": prompt}])
...
原因分析:
报错 Invalid input type <class 'dict'>. Must be a PromptValue, str, or list of BaseMessages 是由于向 ChatOpenAI 的 generate() 方法传递了错误的参数类型。
在 LangChain 中,ChatOpenAI 的 generate() 方法接受的是一组 BaseMessages(如 SystemMessage、HumanMessage、AIMessage),而不是原始的 Python 字典
修改后的代码
from langchain_openai import ChatOpenAI
from langchain.schema import SystemMessage, HumanMessage
def chatbot_conversation(prompt):
try:
# 构造消息列表
messages = [
SystemMessage(content="你是一个友好的聊天助手。"),
HumanMessage(content=prompt)
]
response = llm(messages)
return response.content
except Exception as e:
return f"发生错误: {str(e)}"
LangChainDeprecationWarning
报错代码
...
response = llm(messages)
...
原因分析:
报错 LangChainDeprecationWarning: The method BaseChatModel.__call__ was deprecated in langchain-core 0.1.7 and will be removed in 1.0. Use :meth:~invoke instead. 是LangChainDeprecationWarning 提示你正在使用已弃用的方法 BaseChatModel.__call__,该方法将在 LangChain 1.0 中移除。相应的,应该改为使用新的方法 invoke 来调用模型
你需要将代码中的 llm(messages) 替换为 llm.invoke(messages)
修改后的代码
response = llm.invoke(messages)
最终代码
from langchain_openai import ChatOpenAI
from langchain.schema import SystemMessage, HumanMessage
llm = ChatOpenAI(
model_name='gpt-4o-mini',
openai_api_key='sk-XXX', #302.AI后台-使用API-API Keys 生成的API KEY
openai_api_base='https://api.302.ai/v1/chat/completions',
)
# 创建对话函数
def chatbot_conversation(prompt):
try:
# 构造消息列表
messages = [
SystemMessage(content="你是一个友好的聊天助手。"),
HumanMessage(content=prompt)
]
response = llm.invoke(messages)
# 返回生成的回复内容
return response.content
except Exception as e:
return f"发生错误: {str(e)}"
# 运行对话
if __name__ == "__main__":
print("欢迎使用聊天机器人!输入 '退出' 来结束对话。\n")
while True:
user_input = input("你: ")
if user_input.lower() in ["退出", "exit", "bye"]:
print("机器人: 再见!期待下次与你交流。")
break
reply = chatbot_conversation(user_input)
print(f"机器人: {reply}")
运行效果
红线是我提出的问题, 每个问题下面都是机器人的回答, 这收费效果确实比免费的模型强太多了!
感兴趣的朋友们, 欢迎在评论下方留言, 点赞加关注哦, 后面将继续为大家讲解LangChain的一系列用法