一句话一视频智能体---langchain框架代码实现以及低代码平台总结
总体思路:
agent作为调用者,要按剧本->视频的调用方式进行调用这是此agent唯一的功能,所以prompt非常好写

2.script_maker_tool:
此agent为编写剧本agent,我们需要将用户的话语扩充成剧本形式,即整个视频每一分幕展现的样子,此agent只运用到了一个大模型,难度在于prompt的编写,prompt在此不提供但是如下图为此agent的输出可供参考:
3.video_maker_tool:
实现功能最重要的工具,这里运用到了一个库名为:manim,本质上是通过使用manim库输入命令行命令生成的视频,manim库通用使用格式:
from manim import *
class tests(Scene):
def construct(self):
tri = Triangle()
self.play(Rotate(tri, PI))
self.wait()
在prompt中强力要求大模型只输出上述代码格式 最后使用video_maker工具即可生成视频
video_maker代码:
@tool('video_maker_tool',parse_docstring=True)
def video_maker_tool(script: str) -> str:
"""工具函数:根据脚本生成manim动画代码并渲染成视频。
Args:
script: 生成好的动画剧本
Returns:
返回视频的本地URL路径,如果失败则返回错误信息
"""
try:
# 1. 使用LLM生成Manim代码
code_response = video_maker_llm.invoke(prompt_template.format(script=script))
code = code_response.content if hasattr(code_response, 'content') else str(code_response)
# 清理可能的代码块标记
if code.startswith("```python"):
code = code[9:]
code = code.strip()
# 2. 安全检查
try:
check_code_safety(code)
except ValueError as e:
return f"代码安全检查失败: {e}"
# 3. 创建临时目录并渲染视频
with tempfile.TemporaryDirectory() as tmpdir:
script_path = Path(tmpdir) / "tests.py"
script_path.write_text(code, encoding="utf-8")
video_id = str(uuid.uuid4())
host_video_path = VIDEO_DIR / f"{video_id}.mp4"
try:
# 设置环境变量以解决中文编码问题
env = os.environ.copy()
env["PYTHONIOENCODING"] = "utf-8"
# 运行Manim渲染
result = subprocess.run(
["manim", "-pqm", str(script_path), "tests"],
cwd=tmpdir,
capture_output=True,
timeout=600,
env=env
)
# 安全解码输出
stdout_str = result.stdout.decode('utf-8', errors='replace')
stderr_str = result.stderr.decode('utf-8', errors='replace')
if result.returncode != 0:
err = stderr_str or stdout_str
return f"Manim渲染失败: {err}"
# 查找生成的视频文件
mp4_files = list(Path(tmpdir).rglob("tests*.mp4"))
if not mp4_files:
return "未找到生成的视频文件"
# 复制视频到目标目录
import shutil
shutil.copy(mp4_files[0], host_video_path)
# 返回本地URL
return f"videos/{video_id}.mp4"
except subprocess.TimeoutExpired:
return "渲染超时"
except Exception as e:
return f"渲染过程中出错: {str(e)}"
except Exception as e:
return f"视频生成失败: {str(e)}"
安全验证可以让ai生成 避免篇幅过长这里省略
总结:
大部分代码可以通过ai进行生成,如安全验证,video_maker_tool此工具,以及manim代码的使用与生成,作为调用ai的人员,主要工作是构思系统以及选用工具,不只有manim库可以达到这种效果,moviepy也可以,但是trea使用moviepy会有bug所以这里不做选用,调用大模型要锻炼自身对prompt的编写,不提供prompt也是这个原因
低代码平台:
整体来说实现和上述大同小异,唯一需要注意的是:
代码节点中是调用api形式实现的,为什么要调用api,因为云端并没有manim等库,所以就算代码写的是manim代码的解码编写也是无法运行的,这里需要使用到ngrok将自己电脑上的端口暴露,再使用低平台链接即可
代码节点:
import json
import requests
import urllib3
import asyncio
from typing import Dict, Any
# 禁用SSL警告(对于ngrok等自签名证书)
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
async def main(args) -> Dict[str, Any]:
# 获取输入参数
params = args.params
code_input = params.get('code', '') or params.get('input', '')
# 处理转义字符和格式问题
if code_input and isinstance(code_input, str):
# 移除多余的双引号
if code_input.startswith('"') and code_input.endswith('"'):
code_input = code_input[1:-1]
# 处理多层转义字符
# 将 \\n 转换为 \n,将 \\" 转换为 "
code_input = code_input.replace('\\\\n', '\n').replace('\\\"', '"')
code_input = code_input.replace('\\n', '\n').replace('\\"', '"')
# 验证输入参数
if not code_input:
ret = {
"success": False,
"error": "Valid code is required",
"status": 400,
"debug_info": {
"received_params": list(params.keys()),
"code_preview": str(params.get('code', ''))[:100] if params.get('code') else 'No code provided'
}
}
return ret
# 检查代码是否包含Manim必要元素
if 'from manim import' not in code_input and 'class' not in code_input:
ret = {
"success": False,
"error": "The provided code does not appear to be valid Manim code",
"status": 400,
"code_preview": code_input[:200]
}
return ret
# API端点URL
api_url = "your_ngrok"
# 准备请求数据
request_data = {
'code': code_input
}
try:
# 设置请求头
headers = {
'Content-Type': 'application/json',
'ngrok-skip-browser-warning': 'true'
}
# 使用线程池执行同步的requests调用,避免阻塞事件循环
loop = asyncio.get_event_loop()
response = await loop.run_in_executor(
None,
lambda: requests.post(
api_url,
json=request_data,
headers=headers,
verify=False,
timeout=6000
)
)
# 获取响应数据
try:
response_data = response.json()
except ValueError:
response_data = {'detail': response.text}
# 检查响应状态
if response.ok:
ret = {
"success": True,
"video_url": response_data.get('video_url', ''),
"message": "Animation rendered successfully",
"status": response.status_code,
"response": response_data
}
else:
ret = {
"success": False,
"error": response_data.get('detail', 'Unknown error'),
"status": response.status_code,
"response": response_data
}
except requests.exceptions.Timeout:
ret = {
"success": False,
"error": "Request timeout",
"status": 408
}
except requests.exceptions.ConnectionError:
ret = {
"success": False,
"error": "Connection error - could not reach the API",
"status": 0
}
except Exception as e:
ret = {
"success": False,
"error": f"Unexpected error: {str(e)}",
"status": 500
}
return ret
其他低代码平台无难度,唯一需要注意仅上述内容
更多推荐


所有评论(0)