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

news2025/2/24 2:23:45

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%免费】🆓

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1889876.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

QAM MMA

MMA是改进的CMA,有RCA和CMA的优点,还能对相位误差进行修正。 N 5e5; % 仿真符号数 M 16; % QAM16msg randi([0 M-1],N,1); % 产生随机符号 tx qammod(msg,M); % QAM调制test_snr 20:5:30; …

采用Java语言+开发工具 Idea+ scode数字化产科管理平台源码,产科管理新模式

采用Java语言开发工具 Idea scode数字化产科管理平台源码,产科管理新模式 数字化产科管理系统是现代医疗信息化建设的重要组成部分,它利用现代信息技术手段,对孕产妇的孕期管理、分娩过程及产后康复等各个环节进行数字化、智能化管理&#xf…

【总线】AXI4第七课时:AXI的额外的控制信息(PROT和CACHE)

大家好,欢迎来到今天的总线学习时间!如果你对电子设计、特别是FPGA和SoC设计感兴趣,那你绝对不能错过我们今天的主角——AXI4总线。作为ARM公司AMBA总线家族中的佼佼者,AXI4以其高性能和高度可扩展性,成为了现代电子系统中不可或缺的通信桥梁…

安乃达挂牌上交所:营收放缓净利润下滑,业绩风险如何规避?

《港湾商业观察》施子夫 7月3日,冲刺上交所主板刚满2年的安乃达驱动技术(上海)股份有限公司(以下简称安乃达,603350.SH)将正式挂牌上市。 据悉,此次安乃达公开发行数量为2900万股,…

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【18】认证服务02—微博社交登录

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【18】认证服务02—微博社交登录 微博社交登录图示原理前置准备实现流程完整代码 参考 微博社交登录 OAuth: OAuth(开放授权)是一个开放标准&#xff0…

Python-Tkinter+Logging+Sqlserver项目结合

参考文章: https://www.jb51.net/article/283745.htm 目录: common(文件夹) – base.py – config_reader.py – dosqlserver.py – log.py txt(空文件夹,后面会自动生成txt文件在该文件夹下面) 1.txt 2.txt env.…

html+js+css美观好看的动态404界面

中间的那一段话(root开头的那一句)是逐字输出的 那段话显示完后,自动显示超大号字体404 来都来了点个赞,关注一下呗😄,本人发誓:你关注我,马上关注你 界面 源码在图片下面…

【ONE·Linux || 高级IO(一)】

总言 主要内容:介绍五种IO模型的基本概念、学习IO多路转接(select、poll编程模型)。       文章目录 总言1、问题引入1.1、网络通信与IO1.2、五种IO模型1.2.1、举例引入1.2.2、IO模型具体含义介绍1.2.2.1、阻塞式IO1.2.2.2、非阻塞轮询检…

什么是带有 API 网关的代理?

带有 API 网关的代理服务显著提升了用户体验和性能。特别是对于那些使用需要频繁创建和轮换代理的工具的用户来说,使用 API 可以节省大量时间并提高效率。 了解 API API,即应用程序编程接口,是服务提供商和用户之间的连接网关。通过 API 连接…

智能数字人系统的技术难点

数字人系统,也称为智能数字人系统或虚拟数字人系统,是指利用人工智能技术构建的虚拟人物形象,能够与人进行自然交互的系统。数字人系统涉及多项技术,其开发和应用存在以下技术难点。北京木奇移动技术有限公司,专业的软…

KES数据库实践指南:探索KES数据库的事务隔离级别

并发控制 并发控制的重要性 并发控制是数据库管理系统中的一个核心概念,它确保在多用户环境中,对数据库的并发访问不会破坏数据的完整性和一致性。 当多个用户同时对数据库进行读写操作时,如果缺乏有效的并发控制机制,可能会导致数…

HexPlane: A Fast Representation for Dynamic Scenes(总结图)

图1。用于动态三维场景的 Hex刨面。我们没有从深度 MLP 中回归颜色和不透明度,而是通过 HexPlann 显式地计算时空点的特征。配对一个微小的 MLP,它允许以上100倍加速匹配的质量。 图2。方法概述。Hex刨包含六个特征平面,跨越每对坐标轴(例如…

ctfshow web sql注入 web242--web249

web242 into outfile 的使用 SELECT ... INTO OUTFILE file_name[CHARACTER SET charset_name][export_options]export_options:[{FIELDS | COLUMNS}[TERMINATED BY string]//分隔符[[OPTIONALLY] ENCLOSED BY char][ESCAPED BY char]][LINES[STARTING BY string][TERMINATED…

Python 生成Md文件带超链 和 PDF文件 带分页显示内容

software.md # -*- coding: utf-8 -*- import os f open("software.md", "w", encoding"utf-8") f.write(内部测试版2024 MD版\n) for root, dirs, files in os.walk(path): dax os.path.basename(root)if dax "":print("空白…

UNIAPP_顶部导航栏右侧添加uni-icons图标,并绑定点击事件,自定义导航栏右侧图标

效果 1、导入插件 uni-icons插件:https://ext.dcloud.net.cn/plugin?nameuni-icons 复制 uniicons.ttf 文件到 static/fonts/ 下 仅需要那个uniicons.ttf文件,不引入插件、单独把那个文件下载到本地也是可以的 2、配置页面 "app-plus":…

Hi3861 OpenHarmony嵌入式应用入门--TCP Server

本篇使用的是lwip编写tcp服务端。需要提前准备好一个PARAM_HOTSPOT_SSID宏定义的热点,并且密码为PARAM_HOTSPOT_PSK LwIP简介 LwIP是什么? A Lightweight TCP/IP stack 一个轻量级的TCP/IP协议栈 详细介绍请参考LwIP项目官网:lwIP - A Li…

Ollama+OpenWeb UI搭建最简单的大模型交互界面

Open WebUI是一个专为大型语言模型(LLMs)设计的Web用户界面。这个界面提供了一个直观、响应迅速且易于使用的平台,使用户能够与本地运行的语言模型进行交互,就像与云服务中的模型交互一样。可以非常方便的调试、调用本地模型。你能…

Linux运维之管道符、重定向与环境变量

前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除 目录 一、输入输出重定向 二、管道命令符 三、命令行的通配符 四、常用的转义字符 五、重要的环境变量 致谢 一、输入输出重定向 输入重定向是…

快速下载!Windows 7旗舰版系统:集成所有补丁!

微软对Windows7系统停止支持后,Windows7设备不再收到安全补丁程序、修补程序。尽管如此,许多用户仍然认为Windows7是最好用、最经典的系统。有用户就特别喜欢Windows7旗舰版系统,那么接下来系统之家小编为大家带来的全补丁版本的Windows7系统…

C++精解【10】

文章目录 读写文件概述example csv读文件读取每个字段读取机器学习数据库iris constexpr函数GMP大整数codeblock环境配置数据类型函数类 EigenminCoeff 和maxCoeffArray类 读写文件 概述 fstream typedef basic_fstream<char, char_traits<char>> fstream;此类型…