LangGraph进阶:手把手教你打造电影脚本AI

LangGraph是著名的大模型开发框架LangChain推出的用于构建基于复杂工作流的LLM应用的开发库。LangGraph把任务的节点与关系用Graph结构来定义以支持更多样更复杂的应用场景,特别是:

  • 实现包含循环、迭代等复杂工作流的高级RAG范式

  • 需要更灵活控制的Agent应用,如指定Tool、增加人机交互等

  • 多智能体系统(Multi-Agent System)的构建

我们在之前的文章中曾经介绍过LangGraph实现C-RAG,本文将分享一个如何使用LangGraph构建一个创作电影场景与脚本的多智能体应用

关于多智能体系统

AI智能体是一个基于大模型的具备自我感知、规划与行动能力的AI应用。而多智能体系统(MAS)顾名思义就是由多个AI智能体构成,通过相互关联与协作共同完成任务的智能体系统。

MAS可以是每个智能体有自己独立的LLM、提示词、Tools或者其他自定义代码,用来与其他智能体协作,比如一个虚拟的AI软件公司,可以由多个独立的LLM智能体来担任架构师、程序员、测试人员等多个角色;也可以是一个LLM在不同的提示下扮演不同的角色,比如在一个电影虚拟世界中,同一个LLM根据提示扮演不同的虚拟人物。

电影创作的多智能体应用

在这个应用中,我们的目标是实现一个能够自动创建电影场景、并能够代入场景中的多个角色,模拟对话生成台词脚本,最后输出剧本的LangGraph应用。在这个应用中,需要AI完成的任务是:

  • 场景创建:让AI根据简单输入创建一个电影场景与若干角色。

  • 角色模拟与创作:AI模拟场景中的不同角色进行脚本创作,推动情节发展。

设计如下的Graph图,来表示这个应用的工作流:

大致的流程描述如下:

  • create_scene:用AI创作一个简单电影场景与若干角色。

  • select_speaker:AI根据情节发展选择与切换人物角色,除非故事结束。

  • handle_dialogue:AI模拟选择的人物角色,根据情节发展进行多轮对话。

  • write:完成后将会把整个电影场景与对话脚本输出成文件。

这里的多智能体体现在AI会根据提示扮演不同的角色,并根据情节发展做自主对话。其中角色的切换和扮演由select_speaker与handle_dialogue循环进行,直到满足结束条件(故事结束或者到达最大对话次数)。

用LangGraph实现应用

现在根据上面的Graph来实现这个应用。先做一个简单的准备工作,实现一个LLM调用方法,这里我们使用本地的Ollama加载qwen2中文模型:

from typing import Dict, TypedDict, Optional  
from langgraph.graph import StateGraph, END   
from langchain.output_parsers import CommaSeparatedListOutputParser  
from langchain_community.llms import Ollama  
from langchain_openai import ChatOpenAI  
from docx import Document  
  
# 模型调用  
llm_qwen = Ollama(model='qwen2')  
llm_openai = ChatOpenAI(model='gemini-pro')  
def llm(x):  
    response = llm_qwen.invoke(x)  
    return response

【定义提示词】

我们需要定义如下大模型使用的提示词,分别用来:

  • **创建场景:**根据输入的题材创建一个简单场景及相关角色

  • 提取角色:也就是AI将要扮演的电影中的多个角色名称

  • 角色选择:根据情节发展选择下一个登场的角色

  • 角色模拟:让AI切换扮演电影中的不同角色进行对话并推动情节发展

prompt_scene = "设计一个需要台词的电影场景,题材是:{}。简单描述故事的背景和角色名称,但不要设计台词。不超过100字。角色不超过4个。"   prompt_roles = "识别执行此电影场景所需的不同角色,仅以逗号分隔的列表形式输出最简单的角色名称,角色名称不要包含头衔或称呼、称号、昵称等。这是电影场景:{}"   prompt_select_speaker = """   请根据电影场景、已有对话内容,从以下角色中选出适合下一个说话的人。   如果没有对话内容,请选择一个角色开始对话。如果故事结束,输出END。``-----------   {}   -----------    请仅输出以上的角色名称,名称必须完全匹配。   电影场景:   -----------   {}    -----------   当前对话内容:   -----------   {}    -----------   """   prompt_speak = """   你现在是{},根据下面对话和场景,说出你的下一段台词。输出格式:   ------   {}:台词   ------   要求:   1. 台词与场景和角色的设定相符。   2. 台词能推动剧情发展。   3. 不要重复之前的台词。   到目前为止的对话内容:   ----------   {}   ----------   电影场景:   ----------   {}   ----------   """

【定义GraphState】

这是LangGraph工作流运行中的共享状态数据,也就是各个流程节点之间交换的数据,通常把流程中需要共享的数据在此统一定义。这里我们做如下定义:

# state定义   class GraphState(TypedDict):       #下一个说话者       next_speaker: Optional[str] = None          #对话历史       history: Optional[str] = None          #当前对话内容       current_response: Optional[str] = None          #当前说话者       current_speaker: Optional[str] = None          #剩余对话轮数,为0则结束       dialogues_left: Optional[int]=None          #电影场景       scene: Optional[str]=None          #电影题材       subject: Optional[str]=None          #电影角色       roles: Optional[str]=None`    `#最后输出       results: Optional[str]=None

【创建场景与角色:create_scene】

根据设定主题生成一个电影场景与故事背景,并从场景中抽取出多个角色用于后续的AI模拟。角色存放到roles,场景存放到scene:

#创建场景与角色  
def create_scene(state):  
    scene = llm(prompt_scene.format(state.get('subject')))  
    actors = llm(prompt_roles.format(scene))  
  
    output_parser = CommaSeparatedListOutputParser()  
    roles = output_parser.parse(actors)  
  
    print(f"Scene created: {scene}")  
    print(f"Actors created: {roles}\n")  
  
    return {"scene":scene,"roles":roles}

【角色选择】

根据场景、对话历史、角色列表选择下一个合适对话的角色;如果输出为END,表示故事与对话结束。

#选择说话者  
def select_speaker(state):  
    speaker = state.get('current_speaker')  
    scene = state.get('scene')  
    summary = state.get('history', '').strip()  
    roles = state.get('roles')  
      
    next_speaker = llm(prompt_select_speaker.format(','.join(roles),scene,summary))  
      
    if next_speaker == "END":  
        return {"dialogues_left":0}  
      
    return {"next_speaker": next_speaker}

【角色模拟对话】

LLM根据提示词扮演不同的角色进行对话,对话需要基于场景与历史对话进行推理创作,完成后更改相关的state中信息:

#对话处理  
def handle_dialogue(state):  
    summary = state.get('history', '').strip()  
    count = state.get('dialogues_left')  
    next_speaker = state.get('next_speaker', '').strip()  
    roles = state.get('roles')  
    scene = state.get('scene')  
      
    index = roles.index([x for x in roles if x in next_speaker][0])  
    prompt = prompt_speak.format(roles[index],roles[index],summary,scene)   
    argument = llm(prompt)  
      
    print(f"{argument}\n")  
    return {"history":summary+'\n'+argument,  
            "current_speaker":roles[index],  
            "current_response":argument,  
            "dialogues_left":count-1}

【生成剧本文件】

这是最后的任务节点,把之前的创作生成一个word文件保存:

#写入剧本  
def write(state):  
  
    # Save conversation to a Word document  
    doc = Document()  
          
    # Add scene  
    scene = state['scene']  
    doc.add_heading('Scene', level=1)  
    doc.add_paragraph(scene)  
          
    # Add roles  
    roles = state['roles']  
    doc.add_heading('Roles', level=1)  
    doc.add_paragraph(', '.join(roles))  
          
    # Add dialogue history  
    history = state['history']  
    doc.add_heading('Dialogue History', level=1)  
    doc.add_paragraph(history)  
          
    # Save the document  
    doc.save('movie.docx')  
  
    return {"results":"剧本已生成"}

【定义Workflow】

所有的节点都已经准备完毕,现在我们可以定义应用的workflow。定义一个LangGraph的工作流的典型步骤为:

  • **增加节点:**将上面创建的场景与角色创建、角色选择、角色模拟、生成剧本等通过add_node加入

  • **增加边(节点关系):**按照之前设计的工作流进行连接,唯一需要注意的是流程结束条件的判断,需要使用条件函数来定义“条件边”,使得流程在场景结束或者对话次数达到上限后终止

  • **编译工作流:**生成应用

#条件函数  
def check_end(state):  
    return "end" if state.get("dialogues_left")==0 else "continue"  
  
workflow = StateGraph(GraphState)  
  
#增加节点  
workflow.set_entry_point("create_scene")  
workflow.add_node("create_scene", create_scene)  
workflow.add_node("select_speaker", select_speaker)  
workflow.add_node("handle_dialogue", handle_dialogue)  
workflow.add_node("write",write)  
  
#增加边  
workflow.add_edge('create_scene', "select_speaker")  
workflow.add_conditional_edges(  
    "select_speaker",  
    check_end,  
    {  
        "continue": "handle_dialogue",  
        "end": "write"  
    }  
)  
workflow.add_conditional_edges(  
    "handle_dialogue",  
    check_end,  
    {  
        "continue": "select_speaker",  
        "end": "write"  
    }  
)  
workflow.add_edge('write', END)  
  
#编译  
app = workflow.compile()

【测试应用】

现在我们可以简单测试这个自动生成电影场景与脚本的应用,看看效果如何,运行如下代码:

#运行  
conversation = app.invoke({'dialogues_left':20,  
                           'next_speaker':'',  
                           'history':'',  
                           'current_response':'',  
                           'subject':'一个关于三国的搞笑短视频',},  
                           {'recursion_limit':50})

运行完成后,可以打开当前目录生成的movie.docx文件,查看创作的场景与台词脚本:

小结

如何学习AI大模型?

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

在这里插入图片描述

👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

在这里插入图片描述

1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值