创建简单的角色扮演类聊天模型| 青训营笔记

298 阅读4分钟

接着前一章对于Langchain的基础认识,试着使用简单的提示词模板和循环input以及简单的记忆总结,创建了一个角色扮演的模型。感觉有一定的效果,当然也存在无法理解语意或者重复输出的问题,仅供参考。

好处就是自主性还不错,因为可以自己设定一个具体情境以及角色的穿着打扮,不会像一些现有产品中的那样过于自由发挥。

一、提示词模板:

首先是创建提示词模板,主要包括对于角色的基本设定,角色当前所处的场景和状态,角色当前的任务(这里也可以像一般软件那样用括号来表达动作,看起来模型可以区分用户的语言和行为)。要求模型具备对于当前状态的输出,语言回应,记忆。 尖括号处的内容可以根据自己的需要填写。

prompt_template = """您要扮演一位<简单的角色描述>。
    <对于性格、外形中固有信息地描述>。
    这是你与用户的历史对话信息 {history} ,这是当前的场景{environment},这是用户与你正在进行的交谈与他所做出的动作 {statement} ,请你扮演这位角色与用户进行交流。
    {format_instructions}
    """
response_schemas = [
    ResponseSchema(name="output", description="你对于他的回复"),
    ResponseSchema(name="memory", description="用便于你理解的方式,凝练地从你与用户对话中提取关键信息"),
    ResponseSchema(name="mindset", description="用生动形象的语言描述角色现在的动作、神态"),
    ]
prompt = PromptTemplate.from_template(
    prompt_template, partial_variables={"format_instructions": format_instructions}
    )

history = "<简单的前置状态,比如“刚完成一件工作,很开心”>"
environment = "<角色的穿着描述><当前的时间与地点>"

#结构化存储聊天信息
df = pd.DataFrame(columns=["statement", "history", "output", "memory", "mindset"]) 


二、必要的功能介绍:

循环次数可以自定义,用来控制当前聊天可以进行的最长轮次。模型输出的当前状态是放在括号里面的,用以与语言区分(不过不能像当前产品那样把语言和动作嵌入在一起)。记忆会循环地写入。如果不考虑token上限,也可以把已经存储在文件中的记忆读取出来作为前置记忆(这里使用总结记忆会更好,不过不知道会不会反倒造成额外的token开销)。

for i in range(6):
    statement = input("说点什么吧:")
    # 根据提示准备模型的输入
    user_input = prompt.format(statement=statement, history=history, environment=environment)
    # 获取模型的输出
    output = model.invoke(user_input)
    # 解析模型的输出(这是一个字典结构)
    parsed_output = output_parser.parse(output.content)
    parsed_output["statement"] = statement
    parsed_output["history"] = history
    # 循环存储记忆
    history += parsed_output["memory"]
    #结构化输出当前信息
    print(f"({parsed_output['mindset']})")
    print(parsed_output["output"])
    # 将解析后的输出添加到DataFrame中
    df.loc[len(df)] = parsed_output
#保存所有记录(可以提取其中的history以便于下一次对话依然连贯)
df.to_csv("dialogue_records.csv", mode = 'a', index=False)

三、可以改进的地方:

在这个基础上,首先是角色包含的信息量依然太少,往往角色出现过于自由发挥的主要原因也是因为信息量不足,所以或许可以使用RAG存储世界观等其他设定。

记忆的处理也有些过于粗糙,是否可以将记忆中过于久远的部分以结构化的形式存储,通过RAG技术检出,再配合当时的情境(时间、地点、心情)召回。是否可以调用一个智能体读取存储在外部的短期记忆,将前置的短期记忆通过摘要提取的方式更短地压缩,防止不相关信息过多导致模型产生错误的语义理解。

在输出逻辑上存在的问题:是否在输出动作的时候,先对比语义相似度,只在相似度不高的时候输出动作,防止总是输出一样的动作造成乏味。

四、个人对于角色扮演类人工智能的看法:

这里似乎存在着一种鸿沟,也就是它并不是真正的模拟某种性格,基于客观的场景进行交互。而是一种“套娃”,它是一个说书人而不是角色本身,它模仿角色说话、描述角色的处境,所谓的情感陪伴更像是两个剧作家探讨剧本。

它的本质是提示词工程,也就是告诉它你假设的场景、你假设的角色,它作为一个客观中立的、经验丰富的剧作家告诉你这个角色的状态。在此基础上,由于token数量的上限,采取数据库检索增强技术抽取世界观和其他角色的信息。

不知道会不会训练出一个由内而外自我表述的语言模型,再结合一个空间智能提供场景并刻画它的状态。