(二)手把手地教, 带你一步步学会使用 LLM 搭建自己的小机器人

444 阅读4分钟

【本文正在参加金石计划附加挑战赛——第一期命题】

前言

在上一篇文章, 我曾提到过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便可以拿来使用了.

image.png

你可以全局设置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 是由于向 ChatOpenAIgenerate() 方法传递了错误的参数类型。

LangChain 中,ChatOpenAIgenerate() 方法接受的是一组 BaseMessages(如 SystemMessageHumanMessageAIMessage),而不是原始的 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}")

运行效果

image.png

红线是我提出的问题, 每个问题下面都是机器人的回答, 这收费效果确实比免费的模型强太多了!

感兴趣的朋友们, 欢迎在评论下方留言, 点赞加关注哦, 后面将继续为大家讲解LangChain的一系列用法