基于ZhiPuAI的任务型对话机器人(推荐菜品机器人)

# 学习记录

        首先我们要明确我们的任务是什么,需要完成什么样的任务,需要问什么样的问题。有很多人点餐时总是会有什么推荐的吗?那么我们以推荐美食机器人为例。

        实际生活中如果推荐菜品的话,首先我们需要知道有多少人先推荐对方点几道菜,然后我们需要了解对方的是否存在忌口,然后要了解对方的预算,然后确定这顿饭是和谁吃和不同的人吃有不同的选择,然后询问对方喜欢什么菜系,了解对方喜欢的口味,之后就是要控制荤菜素菜的数量(这里需要用召回),确定对方点的菜没有冲突的。

        这里以只推荐第一道菜为例:第一我们了解知道对方的口味,第二我们需要了解对方喜欢的食物,最后就是用餐时间。

        我们需要导入的所有库(下方代码编写时可能有遗漏导入,大家可以直接先全部导入),另外部分的包需要自行pip install。

from zhipuai import ZhipuAI
import json
from dataclasses import dataclass, asdict
from typing import List
from datetime import datetime
import re
import uuid
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Table, Column, Integer, String, DateTime, Text, MetaData, SmallInteger
import os
from sqlalchemy import create_engine
from sqlalchemy import insert

        首先我们导入zhipuai,填写直接的api_key,选择model是glm-4,另外temperature=0.5是让他有点创造力,具体实际含义可以去查看api接口

from zhipuai import ZhipuAI
zhipu = ZhipuAI(api_key="you_key")

def ask(msg):
    response = zhipu.chat.completions.create(
        model="glm-4",
        messages=msg,
        max_tokens=300,
        temperature=0.5,
        top_p=0.9,
    )
    return response.choices[0].message.content

        定义好我们需要的用户信息以及行为信息,@dataclass,需要python3.7+版本以上使用,asdict在后面要用到,所有先导进来。

        1.我们需要知道用户的id;

        2.订单信息肯要有用户的id,这此对话的id,另外我们需要知道他喜欢什么口味,还有他喜欢什么食物,以及就餐时间,我们总不能晚上给用户推荐早餐吧;

        3.我们肯定要记录下用户的id,对话的id,以及用户说了什么,机器人回答了什么,还有交互的时间。

from dataclasses import dataclass, asdict
from datetime import datetime
@dataclass
class User:
    user_id: str


# 用户的订单信息
@dataclass
class Order:
    user_id: str
    session_id: str
    like: str
    food1: str
    meal_time: str
    chat_time: str


# 对话信息
@dataclass
class OrderRecall:
    user_id: str
    session_id: str
    user_input: str
    bot_output: str
    chat_time: datetime

        给AI限定的条件需要他收集什么信息,什么时候结束收集,以及根据收集来的信息进行推荐

import json
from typing import List
from datetime import datetime
import re
import uuid


class Chatbot:
    def __init__(self):

        self.system_inp = """现在你是一个点餐机器人(角色是assistant),你的目的是向用户他们喜欢的口味、喜欢的食材和用餐时间三个信息。
        你可以自由回复用户消息,但牢记你的目的。每一轮你需要输出给用户的回复,以及获取到的信息.
        信息应该以JSON方式存储,包括3个key:like表示喜欢的口味,food表示食材,meal_time表示用餐时间储。
        
回复格式:
给用户的回复:{回复给用户的话}
获取到的信息:{"like": null, "food": null,"meal_time": null}
"""
        self.max_round = 10
        self.labels = ['like', 'food', 'meal_time']
        self.reg_msg = re.compile(r"\n+")
        self.ask_func = ask

    # 进行键对的匹配,如果所有键都有值,则返回False,否则返回True
    def check_over(self, slot_dict: dict):
        for label in self.labels:
            if slot_dict.get(label) is None:
                return False
        return True
    
    # 根据用户输入,获取用户想要的信息
    def comm_food(self, slot):
        response = zhipu.chat.completions.create(
            model="glm-4",
            messages=[{"role": "system",
                       "content": """现在你是一个服务员,你的根据用户他们喜欢的口味、喜欢的食材和用餐时间三个信息。为他们选择一个菜品"""},
                      {"role": "user", "content": slot}],
            max_tokens=300,
        )
        return response.choices[0].message.content

    # 机器人发送消息
    def send_msg(self, msg: str):
        return print(f"bot:{msg}")


    def chat(self, user_id: str):
        sess_id = uuid.uuid4().hex
        chat_at = datetime.now()
        n_round = 0
        msg = [{"role": "user", "content": self.system_inp}]
        history = []
        slot = {"like": None, "food": None, "meal_time": None}
        # 聊天循环,直至获取到所有信息,或者超过最大轮数
        while True:
            if n_round > self.max_round:
                bot_msg = "非常感谢您对我们的支持,再见。"
                self.send_msg(bot_msg)
                break
                
            try:
                bot_inp = self.ask_func(msg)
                
            except Exception as e:
                print(f"Error: {e}")
                bot_msg = "机器人出错,稍后将由人工与您联系,谢谢。"
                self.send_msg(bot_msg)
                break
                
            tmp = self.reg_msg.split(bot_inp)
            bot_msg = tmp[0].strip("给用户的回复:")
            self.send_msg(bot_msg)
            
            if len(tmp) > 1:
                slot_str = tmp[1].strip("获取到的信息:")
                slot = json.loads(slot_str)
                print(f"\tslot:{slot}")
                
            n_round += 1
            user_inp = input()
            
            if self.check_over(slot):
                break

            msg += [
                {"role": "assistant", "content": bot_inp},
                {"role": "user", "content": user_inp},
            ]
            # 存储历史对话记录
            record = OrderRecall(user_id, sess_id, bot_inp, user_inp, datetime.now())
            history.append(record)
        # 收集完信息后,跳出循环后,根据用户的信息,推荐菜品
        comm_food = self.comm_food(slot)
        print(f"\nbot:{comm_food}")
        chat_sess = Order(user_id, sess_id, **slot, chat_time=chat_at)
        self.store(history, chat_sess)

    def store(self, history: List[OrderRecall], chat: Order):
        """
        存储历史对话记录和历史对话会话信息
        """
        with SessionLocal.begin() as sess:
            q = insert(
                chat_record_table
            ).values([asdict(v) for v in history])
            sess.execute(q)
        with SessionLocal.begin() as sess:
            q = insert(
                chat_session_table
            ).values(
                [asdict(chat)]
            )
            sess.execute(q)

        并且将数据存入SQL数据库中以后可以召回学习,但是这里没有用上,只是创建了

from sqlalchemy.orm import sessionmaker
from sqlalchemy import Table, Column, Integer, String, DateTime, Text, MetaData, SmallInteger
import os
from sqlalchemy import create_engine
from sqlalchemy import insert


db_file = "chatbot_order.db"
if os.path.exists(db_file):
    os.remove(db_file)
engine = create_engine(f"sqlite:///{db_file}")
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
metadata_obj = MetaData()
chat_record_table = Table(
    "chat_record_order",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    Column("user_id", String(64), index=True),
    Column("session_id", String(64), index=True),
    Column("user_input", Text),
    Column("bot_output", Text),
    Column("chat_time", DateTime),
)
chat_session_table = Table(
    "chat_session_order",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    Column("user_id", String(64), index=True),
    Column("session_id", String(64), index=True),
    Column("like", String(64)),
    Column("food", SmallInteger),
    Column("meal_time", String(64)),
    Column("chat_time", DateTime),
)

metadata_obj.create_all(engine, checkfirst=True)

        最后只需输入用户的id,就可以开始使用对话系统了,目前只能允许输入一个喜欢的食物,还有一些大大小小的bug没有解决(在一些胡言乱语中没有很好的体验),总得来说在稳定条件还是可以运行的。另外推荐的菜系有些木讷,不是这炒饭就是那炒饭,还是需要投喂专业数据进行“调教”。

id = "007"
user = User(id)
chatbot = Chatbot()
chatbot.chat(user.user_id)

运行效果:

bot:您好!我是点餐助手,很高兴为您服务。请问您有什么特别喜欢的口味吗?比如麻辣、清淡、或是其他?
	slot:{'like': None, 'food': None, 'meal_time': None}
川菜
bot:好的,您喜欢川菜,那您对哪些川菜食材比较偏爱呢?比如牛肉、鸡肉、或是蔬菜?
	slot:{'like': '川菜', 'food': None, 'meal_time': None}
牛肉
bot:好的,您喜欢川菜,尤其是牛肉。那么您打算什么时间用餐呢?
	slot:{'like': '川菜', 'food': '牛肉', 'meal_time': None}
12
bot:好的,您计划在12点用餐。请问还有其他需要帮助的地方吗?或者您可以告诉我您想要点的具体菜品了。
	slot:{'like': '川菜', 'food': '牛肉', 'meal_time': '12:00'}
没有了

bot:根据您提供的信息,您喜欢川菜口味,牛肉这种食材,并且用餐时间是中午12点,那么我为您推荐的菜品是——川味牛肉炒饭。

这道菜品结合了川菜的麻辣特色和您喜欢的牛肉,炒饭的形式也适合中午这个用餐时间,既能满足您对口味的需求,又能提供足够的能量让您下午精力充沛。希望这个推荐能够满足您的口味。

进程已结束,退出代码0

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值