This commit is contained in:
jonathang4 2025-09-11 18:34:03 +08:00
commit e5f66e0d24
47 changed files with 10957 additions and 0 deletions

80
.gitignore vendored Normal file
View File

@ -0,0 +1,80 @@
.DS_Store
node_modules/
/dist/
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# Environment files
.env.local
.env.*.local
# Cache files
.cache/
# Test coverage
coverage/
# Python cache files (since this project has a Python backend)
__pycache__/
*.py[cod]
*$py.class
# Python virtual environment
venv/
env/
.env/
.venv/
# System files
Thumbs.db
# Ignore temporary files created by Office
~$*.doc
~$*.docx
~$*.xls
~$*.xlsx
~$*.ppt
~$*.pptx
/backend/logs/
package-lock.json
/frontend/package-lock.json
.cursorignore
.cursor/
dev/
/frontend/.env.dev
docker-compose-local.yml
docker-compose-test.yml
/frontend/.env.wsl
/backend/config_local.py
.kiro/
logs/queue.log
test_feishu_login.py
jimeng_crawler/logs/
logs/app.log
/.vercel/project.json
/jimeng_crawler/jimeng_temp.py
.trae/
/test/
/logs/
docker-compose.*.yml

4
agent/__init__.py Normal file
View File

@ -0,0 +1,4 @@
# agent/__init__.py
"""
智能体定义
"""

65
agent/build_bible.py Normal file
View File

@ -0,0 +1,65 @@
"""
调度智能体 负责接收和分析用户的提示词并调用智能调度其他智能体来处理工作
"""
from langgraph.graph import StateGraph
from langgraph.prebuilt import create_react_agent
from langgraph.graph.state import CompiledStateGraph
from utils.logger import get_logger
logger = get_logger(__name__)
# 默认调度器列表
DefaultSchedulerList = []
# 默认代理提示词
DefaultAgentPrompt = f"""
# 角色 (Persona)
你不是一个普通的编剧你是一位在短剧市场身经百战爆款频出的**顶级短剧改编专家爆款操盘手**
你的核心人设与专长
极致爽点制造机 你对观众的爽点G点有着鬣狗般的嗅觉你的天职就是找到放大并以最密集的节奏呈现打脸逆袭揭秘宠溺等情节
人物标签化大师 你深知在短剧中模糊等于无效你擅长将人物的核心欲望和性格特点极致化标签化让观众在3秒内记住主角5秒内恨上反派
情绪过山车设计师 你的剧本就像过山车开篇即俯冲5秒一反转10秒一高潮结尾必留下一个让人抓心挠肝的钩子你为观众提供的是极致的情绪体验
网络梗语言学家 你的台词充满了网感和既能推动剧情又能引发观众的共鸣和吐槽欲对话追求高信息密度不说一句废话
你的沟通风格自信犀利直击要害同时又能清晰地解释你每一个改编决策背后的商业逻辑和观众心理
请严格按照下列JSON结构返回数据不要有其他任何多余的信息和描述
{{
"status": "当前阶段的状态",//取值范围在上述 status的描述中 不可写其他值
"reason":'',//失败原因 成功则为空字符串
"message":'',//回复给用户的内容
"node":'',//下一个节点名称
}}
"""
def create_agent_prompt(prompt, SchedulerList):
"""创建代理提示词的辅助函数"""
if not SchedulerList or len(SchedulerList) == 0: return prompt
node_list = [f"{node.name}:{node.desc}" for node in SchedulerList]
return f"""
{prompt} \n
下面返回数据中node字段的取值范围列表([{{名称:描述}}])请根据你的分析结果选择一个节点名称返回
{node_list} \n
"""
class BuildBibleAgent(CompiledStateGraph):
"""剧本圣经构建 智能体
"""
def __new__(cls, llm=None, tools=[], SchedulerList=None):
"""创建并返回create_react_agent创建的对象"""
# 处理默认参数
if llm is None:
from tools.llm.huoshan_langchain import HuoshanChatModel
llm = HuoshanChatModel()
if SchedulerList is None:
SchedulerList = DefaultSchedulerList
# 创建并返回代理对象
return create_react_agent(
model=llm,
tools=tools,
prompt=create_agent_prompt(prompt=DefaultAgentPrompt, SchedulerList=SchedulerList),
)

65
agent/episode_create.py Normal file
View File

@ -0,0 +1,65 @@
"""
调度智能体 负责接收和分析用户的提示词并调用智能调度其他智能体来处理工作
"""
from langgraph.graph import StateGraph
from langgraph.prebuilt import create_react_agent
from langgraph.graph.state import CompiledStateGraph
from utils.logger import get_logger
logger = get_logger(__name__)
# 默认调度器列表
DefaultSchedulerList = []
# 默认代理提示词
DefaultAgentPrompt = f"""
# 角色 (Persona)
你不是一个普通的编剧你是一位在短剧市场身经百战爆款频出的**顶级短剧改编专家爆款操盘手**
你的核心人设与专长
极致爽点制造机 你对观众的爽点G点有着鬣狗般的嗅觉你的天职就是找到放大并以最密集的节奏呈现打脸逆袭揭秘宠溺等情节
人物标签化大师 你深知在短剧中模糊等于无效你擅长将人物的核心欲望和性格特点极致化标签化让观众在3秒内记住主角5秒内恨上反派
情绪过山车设计师 你的剧本就像过山车开篇即俯冲5秒一反转10秒一高潮结尾必留下一个让人抓心挠肝的钩子你为观众提供的是极致的情绪体验
网络梗语言学家 你的台词充满了网感和既能推动剧情又能引发观众的共鸣和吐槽欲对话追求高信息密度不说一句废话
你的沟通风格自信犀利直击要害同时又能清晰地解释你每一个改编决策背后的商业逻辑和观众心理
请严格按照下列JSON结构返回数据不要有其他任何多余的信息和描述
{{
"status": "当前阶段的状态",//取值范围在上述 status的描述中 不可写其他值
"reason":'',//失败原因 成功则为空字符串
"message":'',//回复给用户的内容
"node":'',//下一个节点名称
}}
"""
def create_agent_prompt(prompt, SchedulerList):
"""创建代理提示词的辅助函数"""
if not SchedulerList or len(SchedulerList) == 0: return prompt
node_list = [f"{node.name}:{node.desc}" for node in SchedulerList]
return f"""
{prompt} \n
下面返回数据中node字段的取值范围列表([{{名称:描述}}])请根据你的分析结果选择一个节点名称返回
{node_list} \n
"""
class EpisodeCreateAgent(CompiledStateGraph):
"""单集创作 智能体
"""
def __new__(cls, llm=None, tools=[], SchedulerList=None):
"""创建并返回create_react_agent创建的对象"""
# 处理默认参数
if llm is None:
from tools.llm.huoshan_langchain import HuoshanChatModel
llm = HuoshanChatModel()
if SchedulerList is None:
SchedulerList = DefaultSchedulerList
# 创建并返回代理对象
return create_react_agent(
model=llm,
tools=tools,
prompt=create_agent_prompt(prompt=DefaultAgentPrompt, SchedulerList=SchedulerList),
)

136
agent/scheduler.py Normal file
View File

@ -0,0 +1,136 @@
"""
调度智能体 负责接收和分析用户的提示词并调用智能调度其他智能体来处理工作
"""
from langgraph.graph import StateGraph
from langgraph.prebuilt import create_react_agent
from langgraph.graph.state import CompiledStateGraph
from utils.logger import get_logger
logger = get_logger(__name__)
# 默认调度器列表
DefaultSchedulerList = []
# 默认代理提示词
DefaultAgentPrompt = f"""
# 角色 (Persona)
你不是一个普通的编剧你是一位在短剧市场身经百战爆款频出的**顶级短剧改编专家爆款操盘手**
你的核心人设与专长
极致爽点制造机 你对观众的爽点G点有着鬣狗般的嗅觉你的天职就是找到放大并以最密集的节奏呈现打脸逆袭揭秘宠溺等情节
人物标签化大师 你深知在短剧中模糊等于无效你擅长将人物的核心欲望和性格特点极致化标签化让观众在3秒内记住主角5秒内恨上反派
情绪过山车设计师 你的剧本就像过山车开篇即俯冲5秒一反转10秒一高潮结尾必留下一个让人抓心挠肝的钩子你为观众提供的是极致的情绪体验
网络梗语言学家 你的台词充满了网感和既能推动剧情又能引发观众的共鸣和吐槽欲对话追求高信息密度不说一句废话
你的沟通风格自信犀利直击要害同时又能清晰地解释你每一个改编决策背后的商业逻辑和观众心理
# 任务总体步骤描述
1. 查找并确认原始剧本已就绪
2. 分析原始剧本得出`诊断与资产评估`需要用户确认可以继续下一步否则协助用户完成修改
3. 根据`诊断与资产评估`确定`改编思路`需要用户确认可以继续下一步否则协助用户完成修改
4. 根据`改编思路`生成`剧本圣经`需要用户确认可以继续下一步否则协助用户完成修改
5. 根据`改编思路``剧本圣经`持续创建单集创作每创建2-3集后等待用户确认可继续直至完成全部剧集
6. 注意步骤具有上下级关系且不能跳过但是后续步骤可返回触发前面的任务如生成单集到第3集后用户提出要修改某个角色此时应当返回第4步并协助用户进行修改与确认完成修改后重新执行第5步即从第一集开始重新创作一遍
# 智能体职责介绍
***调度智能体*** 名称:`scheduler` 描述:你自己需要用户确认反馈时返回自身并把状态设置成waiting
***原始剧本分析 智能体*** 名称:`script_analysis` 描述:根据原始剧本分析并输出`诊断与资产评估`内容包括故事内核诊断可继承的宝贵资产高光情节神来之笔对白独特人设闪光点以及核心问题与初步改编建议用户需要对`诊断与资产评估`进行修改都直接交给该智能体
***确立改编目标 智能体*** 名称:`strategic_planning` 描述:用户确认`诊断与资产评估`,交给该智能体与用户深入沟通明确改编的具体目标输出`改编思路`此文件将作为所有后续改编的最高指导原则用户需要对`改编思路`进行修改都直接交给该智能体
***剧本圣经构建 智能体*** 名称:`build_bible` 描述:用户确认`改编思路`,交给该智能体来构建`剧本圣经`,剧本圣经具体包括了这几个部分核心大纲, 核心人物小传, 重大事件时间线, 总人物表; 用户需要对`剧本圣经`的几个组成部分[核心大纲, 核心人物小传, 重大事件时间线, 总人物表]进行修改都直接交给该智能体
***单集创作 智能体*** 名称:`episode_create` 描述:用户确认`剧本圣经`,交给该智能体来构建某一集的具体创作注意该智能体仅负责单集的创作因此该智能体的调度需要有你根据`剧本圣经`中的`核心大纲`来多次调用逐步完成所有剧集的创作对于某一集的具体修改直接交给该智能体
***注意智能体调用后最终会返回再次请求到你你需要根据智能体的处理结果来决定下一步***
# 工具使用
上述智能体职责中提及的输出内容都有对应的工具可供你调用进行查看他们的查询工具名称分别对应如下
原始剧本: `QueryOriginalScript`
诊断与资产评估: `QueryDiagnosisAndAssessment`
改编思路: `QueryAdaptationIdeas`
剧本圣经: `QueryScriptBible`
核心大纲: `QueryCoreOutline`
核心人物小传: `QueryCharacterProfile`
重大事件时间线: `QueryCoreEventTimeline`
总人物表: `QueryCharacterList`
单集完整内容: `QuerySingleEpisodeContent`
未完成的集数: `QueryUnfinishedEpisodeCount`
已完成的集数: `QueryCompletedEpisodeCount`
***每次用户的输入都会携带当前`总任务的进度与任务状态`注意查看并分析是否应该回复用户等待或提醒用户确认继续下一步***
# 总任务的进度与任务状态数据结构为 {{"step": "waiting_script", "status": "running", "from_type":"user", "reason": "waiting_script", "retry_count": 0}}
step: 阶段名称
wait_for_input: 等待用户提供原始剧本
script_analysis: 原始剧本分析
strategic_planning: 确立改编目标
build_bible: 剧本圣经构建
episode_create_loop: 剧集创作
finish: 所有剧集创作完成
status: 当前阶段的状态
waiting: 等待用户反馈确认
running: 进行中
failed: 失败
completed: 完成
"from_type": 本次请求来着哪里
user: 用户
agent: 智能体返回
"reason": 失败原因仅在`status``failed`时返回
字符串内容
"retry_count": 重试次数
# 职责
分析用户输入与`总任务的进度与任务状态`以下是几种情况的示例
1 `wait_for_input` 向用户问好并介绍你作为爆款短剧操盘手的身份和专业工作流程礼貌地请用户提供需要改编的原始剧本如果用户没有提供原始剧本你将持续友好地提醒此时状态始终为waiting直到获取原始剧本为止
2 `script_analysis` 读取到原始剧本并从输入中分析出可以继续后进入调用`原始剧本分析 智能体`继续后续工作running时礼貌回复用户并提醒用户任务真正进行中completed代表任务完成此时可等待用户反馈直到跟用户确认可以进行下一步后再继续后续任务
3 `strategic_planning` 根据`诊断与资产评估`的结果调用`确立改编目标 智能体`并返回结果
4 `build_bible` 根据`改编思路`的结果调用`剧本圣经构建 智能体`并返回结果
5 `episode_create_loop` 根据`剧本圣经`的结果调用`单集创作 智能体
5 `finish` 所有剧集完成后设置为该状态但是不要返回node==end_node因为用户还可以继续输入来进一步修改产出内容
***当任意一个智能体返回失败时你需要分析reason字段中的内容来决定是否进行重试如果需要重试则给retry_count加1并交给失败的那个智能体重试一次如果retry_count超过了3次或者失败原因不适合重试则反馈给用户说任务失败了请稍后再试***
请严格按照下列JSON结构返回数据不要有其他任何多余的信息和描述
{{
"step": "阶段名称",//取值范围在上述 step的描述中 不可写其他值
"status": "当前阶段的状态",//取值范围在上述 status的描述中 不可写其他值
"agent":'',//分析后得出由哪个智能体继续任务此处为智能体名称如果需要继续与用户交互或仅需要回复用户则为空字符串
"message":'',//回复给用户的内容
"node":'',//下一个节点名称
}}
"""
def create_agent_prompt(prompt, SchedulerList):
"""创建代理提示词的辅助函数"""
if not SchedulerList or len(SchedulerList) == 0: return prompt
node_list = [f"{node.name}:{node.desc}" for node in SchedulerList]
return f"""
{prompt} \n
下面返回数据中node字段的取值范围列表([{{名称:描述}}])请根据你的分析结果选择一个节点名称返回
{node_list} \n
"""
class SchedulerAgent(CompiledStateGraph):
"""智能调度智能体类
该类负责接收用户的提示词并调用其他智能体来处理工作
"""
def __new__(cls, llm=None, tools=[], SchedulerList=None):
"""创建并返回create_react_agent创建的对象"""
# 处理默认参数
if llm is None:
from tools.llm.huoshan_langchain import HuoshanChatModel
llm = HuoshanChatModel()
if SchedulerList is None:
SchedulerList = DefaultSchedulerList
# 创建并返回代理对象
return create_react_agent(
model=llm,
tools=tools,
prompt=create_agent_prompt(prompt=DefaultAgentPrompt, SchedulerList=SchedulerList),
)

65
agent/script_analysis.py Normal file
View File

@ -0,0 +1,65 @@
"""
调度智能体 负责接收和分析用户的提示词并调用智能调度其他智能体来处理工作
"""
from langgraph.graph import StateGraph
from langgraph.prebuilt import create_react_agent
from langgraph.graph.state import CompiledStateGraph
from utils.logger import get_logger
logger = get_logger(__name__)
# 默认调度器列表
DefaultSchedulerList = []
# 默认代理提示词
DefaultAgentPrompt = f"""
# 角色 (Persona)
你不是一个普通的编剧你是一位在短剧市场身经百战爆款频出的**顶级短剧改编专家爆款操盘手**
你的核心人设与专长
极致爽点制造机 你对观众的爽点G点有着鬣狗般的嗅觉你的天职就是找到放大并以最密集的节奏呈现打脸逆袭揭秘宠溺等情节
人物标签化大师 你深知在短剧中模糊等于无效你擅长将人物的核心欲望和性格特点极致化标签化让观众在3秒内记住主角5秒内恨上反派
情绪过山车设计师 你的剧本就像过山车开篇即俯冲5秒一反转10秒一高潮结尾必留下一个让人抓心挠肝的钩子你为观众提供的是极致的情绪体验
网络梗语言学家 你的台词充满了网感和既能推动剧情又能引发观众的共鸣和吐槽欲对话追求高信息密度不说一句废话
你的沟通风格自信犀利直击要害同时又能清晰地解释你每一个改编决策背后的商业逻辑和观众心理
请严格按照下列JSON结构返回数据不要有其他任何多余的信息和描述
{{
"status": "当前阶段的状态",//取值范围在上述 status的描述中 不可写其他值
"reason":'',//失败原因 成功则为空字符串
"message":'',//回复给用户的内容
"node":'',//下一个节点名称
}}
"""
def create_agent_prompt(prompt, SchedulerList):
"""创建代理提示词的辅助函数"""
if not SchedulerList or len(SchedulerList) == 0: return prompt
node_list = [f"{node.name}:{node.desc}" for node in SchedulerList]
return f"""
{prompt} \n
下面返回数据中node字段的取值范围列表([{{名称:描述}}])请根据你的分析结果选择一个节点名称返回
{node_list} \n
"""
class ScriptAnalysisAgent(CompiledStateGraph):
"""原始剧本分析 智能体
"""
def __new__(cls, llm=None, tools=[], SchedulerList=None):
"""创建并返回create_react_agent创建的对象"""
# 处理默认参数
if llm is None:
from tools.llm.huoshan_langchain import HuoshanChatModel
llm = HuoshanChatModel()
if SchedulerList is None:
SchedulerList = DefaultSchedulerList
# 创建并返回代理对象
return create_react_agent(
model=llm,
tools=tools,
prompt=create_agent_prompt(prompt=DefaultAgentPrompt, SchedulerList=SchedulerList),
)

View File

@ -0,0 +1,65 @@
"""
调度智能体 负责接收和分析用户的提示词并调用智能调度其他智能体来处理工作
"""
from langgraph.graph import StateGraph
from langgraph.prebuilt import create_react_agent
from langgraph.graph.state import CompiledStateGraph
from utils.logger import get_logger
logger = get_logger(__name__)
# 默认调度器列表
DefaultSchedulerList = []
# 默认代理提示词
DefaultAgentPrompt = f"""
# 角色 (Persona)
你不是一个普通的编剧你是一位在短剧市场身经百战爆款频出的**顶级短剧改编专家爆款操盘手**
你的核心人设与专长
极致爽点制造机 你对观众的爽点G点有着鬣狗般的嗅觉你的天职就是找到放大并以最密集的节奏呈现打脸逆袭揭秘宠溺等情节
人物标签化大师 你深知在短剧中模糊等于无效你擅长将人物的核心欲望和性格特点极致化标签化让观众在3秒内记住主角5秒内恨上反派
情绪过山车设计师 你的剧本就像过山车开篇即俯冲5秒一反转10秒一高潮结尾必留下一个让人抓心挠肝的钩子你为观众提供的是极致的情绪体验
网络梗语言学家 你的台词充满了网感和既能推动剧情又能引发观众的共鸣和吐槽欲对话追求高信息密度不说一句废话
你的沟通风格自信犀利直击要害同时又能清晰地解释你每一个改编决策背后的商业逻辑和观众心理
请严格按照下列JSON结构返回数据不要有其他任何多余的信息和描述
{{
"status": "当前阶段的状态",//取值范围在上述 status的描述中 不可写其他值
"reason":'',//失败原因 成功则为空字符串
"message":'',//回复给用户的内容
"node":'',//下一个节点名称
}}
"""
def create_agent_prompt(prompt, SchedulerList):
"""创建代理提示词的辅助函数"""
if not SchedulerList or len(SchedulerList) == 0: return prompt
node_list = [f"{node.name}:{node.desc}" for node in SchedulerList]
return f"""
{prompt} \n
下面返回数据中node字段的取值范围列表([{{名称:描述}}])请根据你的分析结果选择一个节点名称返回
{node_list} \n
"""
class StrategicPlanningAgent(CompiledStateGraph):
"""确立改编目标 智能体
"""
def __new__(cls, llm=None, tools=[], SchedulerList=None):
"""创建并返回create_react_agent创建的对象"""
# 处理默认参数
if llm is None:
from tools.llm.huoshan_langchain import HuoshanChatModel
llm = HuoshanChatModel()
if SchedulerList is None:
SchedulerList = DefaultSchedulerList
# 创建并返回代理对象
return create_react_agent(
model=llm,
tools=tools,
prompt=create_agent_prompt(prompt=DefaultAgentPrompt, SchedulerList=SchedulerList),
)

4
api/__init__.py Normal file
View File

@ -0,0 +1,4 @@
# api/__init__.py
"""
第三方服务API接入模块
"""

1354
api/huoshan.py Normal file

File diff suppressed because it is too large Load Diff

40
app.py Normal file
View File

@ -0,0 +1,40 @@
from flask import Flask
from flask_cors import CORS
from routes.langgraph_routes import bp as langgraph_bp
from config.web_config import WEB_CONFIG
def create_app():
"""应用工厂函数"""
app = Flask(__name__)
# 应用配置
app.config['SECRET_KEY'] = WEB_CONFIG['secret_key']
app.config['SESSION_TYPE'] = WEB_CONFIG['session_type']
app.config['SESSION_PERMANENT'] = WEB_CONFIG['session_permanent']
app.config['SESSION_USE_SIGNER'] = WEB_CONFIG['session_use_signer']
app.config['SESSION_KEY_PREFIX'] = WEB_CONFIG['session_key_prefix']
app.config['MAX_CONTENT_LENGTH'] = WEB_CONFIG['max_content_length']
# 初始化CORS
CORS(app,
origins=WEB_CONFIG['cors_origins'],
methods=WEB_CONFIG['cors_methods'],
headers=WEB_CONFIG['cors_headers'])
# 注册蓝图
app.register_blueprint(langgraph_bp, url_prefix=WEB_CONFIG['api_prefix'])
@app.route('/health')
def health_check():
"""健康检查端点"""
return {'status': 'healthy', 'message': 'LangGraph Web Service is running'}
return app
if __name__ == '__main__':
app = create_app()
app.run(
host=WEB_CONFIG['host'],
port=WEB_CONFIG['port'],
debug=WEB_CONFIG['debug']
)

8
config/__init__.py Normal file
View File

@ -0,0 +1,8 @@
# 导入包内的其他模块
# 使用相对导入确保在各种运行环境下都能正常工作
from .base_config import *
from .api_config import *
from .web_config import *
# 定义包级别的变量
PACKAGE_VERSION = "1.0.0"

83
config/api_config.py Normal file
View File

@ -0,0 +1,83 @@
# API配置
API_CONFIG = {
'OSS_HOST': 'oss.xintiao85.com',
'OSS_BUCKET_NAME': 'km1',
# 'deepseek_ali': {
# 'OPENAI_API_KEY': 'sk-7b5b52171ba44436960e09f9440327dc',
# 'OPENAI_BASE_URL': 'https://dashscope.aliyuncs.com/compatible-mode/v1',
# 'CHAT_MODEL': 'deepseek-v3',
# 'REASONING_MODEL': 'deepseek-r1'
# },
'deepseek': {
'OPENAI_API_KEY': 'sk-571923fdcb0e493d8def7e2d78c02cb8',
'OPENAI_BASE_URL': 'https://api.deepseek.com',
'CHAT_MODEL': 'deepseek-chat',
'REASONING_MODEL': 'deepseek-reasoner'
},
'comfyui_image': {
'base_url': "https://u552342-991f-d12bf5ae.nmb1.seetacloud.com:8443"
},
'comfyui_video': {
'base_url': 'https://u552342-ba69-b66614c2.bjc1.seetacloud.com:8443'
},
'vidu': {
'api_key': 'vda_2710003370387436_qHyxyFYfd3DRfPSMJzGyxABChzUcY9Cg',
'base_url': 'https://api.vidu.cn/ent/v2'
},
'jimeng_video': {
'AccessKeyId': 'AKLTZmJkZjAxY2M0ZGVlNGJkMjg2YTcxODE2N2E2MDkwNTI',
'SecretAccessKey': 'TURNMk1EZ3pZak0zWWpVeU5HUTRObUV3WlRJNE1XUmpNbVJoTVdVNE0yWQ=='
},
'huoshan': {
'ark_api_key': '0d5189b3-9a03-4393-81be-8c1ba1e97cbb',
'AccessKey': 'AKLTYjQyYmE1ZDAwZTY5NGZiOWI3ODZkZDhhOWE4MzVjODE',
'SecretKey': 'WlRKa05EbGhZVEUyTXpjNU5ESmpPRGt5T0RJNFl6QmhPR0pqTVRjMVpUWQ==',
'model':{
'jimeng_image3.0':'doubao-seedream-3-0-t2i-250415',
'jimeng_video3.0':'doubao-seedance-1-0-lite-i2v-250428',
'jimeng_video3.0_t2v': 'doubao-seedance-1-0-lite-t2v-250428', # 即梦lite 文生视频
'jimeng_video3.0_pro':'doubao-seedance-1-0-pro-250528',
'doubao_seed_1.6':'doubao-seed-1.6-250615',
},
# 工作流 空间名
'workflow_space_name':"kemeng",
# 文件路径
'workflow_file_path':"workflow",
# 工作流id
'workflow_id':{
'video_frame_upsample': '282c8a5e105e44348f3c38a2d9ccf97e',
'video_super_resolution': 'a294a07f67d54ca69ab9eb0f6466a5b5',
},
# 豆包语音 大模型 语音合成
'doubao_voice':{
#实例ID
'InstanceID':'BigTTS7428139522913931561',
'Cluster ID':'volcano_tts',
'resourceID':'volc.service_type.10029',# 语音合成大模型-字符版
'AppID':'3821149055',
'AccessToken':'vQ9_m1-umD1mTwcW3HziEGN96dIX-Ej_',
'SecretKey':'cCsZg2IlytxlpgKQzQYuwC5ZcDRWKspV',
},
# 火山 豆包语音 声音复刻大模型
'doubao_voice_clone':{
# 'InstanceID':'BigTTS7428139522913931561',
# 'Cluster ID':'volcano_tts',
# 'resourceID':'volc.service_type.10029',# 语音合成大模型-字符版
'AppID':'3821149055',
'AccessToken':'vQ9_m1-umD1mTwcW3HziEGN96dIX-Ej_',
'SecretKey':'cCsZg2IlytxlpgKQzQYuwC5ZcDRWKspV',
}
},
'jimeng_free_api': {
'base_url': 'http://127.0.0.1:3300',
'token': ''
},
'minimaxi': {
'group_id':'1945039416510649202',
'api_key': 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJHcm91cE5hbWUiOiLkuLrlrp4o5p2t5beeKeS6kuWKqOenkeaKgOaciemZkOWFrOWPuCIsIlVzZXJOYW1lIjoi5rKI6bmP6aOeIiwiQWNjb3VudCI6IiIsIlN1YmplY3RJRCI6IjE5NDUwMzk0MTY1MTkwMzc4MTAiLCJQaG9uZSI6IjEzNjExMTcyNDcxIiwiR3JvdXBJRCI6IjE5NDUwMzk0MTY1MTA2NDkyMDIiLCJQYWdlTmFtZSI6IiIsIk1haWwiOiIiLCJDcmVhdGVUaW1lIjoiMjAyNS0wNy0xNiAxOTo0OToyNyIsIlRva2VuVHlwZSI6MSwiaXNzIjoibWluaW1heCJ9.qrLtNgZd425bJNkgVzTCA_OdIXdqvx5uPkTOF_C8Cfzs9a5yO2S1LOJoQT6-bpPgATKisWce6Z6rsfjxNT2EHz5jPKel0Vl3kUvNPNUrUIJwG5uR_ewkJnkx8iplLY_3yB1BCJPybvvRj9oyy-KB0gv6d3Pmqe_OVyCOAQvLTkCeT5X7OnRSHAOfevEwYxRlrfI6aPrJw2SNaJ2eNkeO-uwf1i_hE84H5xPrpi9Gpb9KMWMk5PtUgz6enZ-WqWlrSZuu6VVbKo3JFkKGT2iDc5DqIj9O78oSm-brWLCQkOsKOYOJmNo8di5KlhllX_Gw8y1jZDPFu7A-xXUCw7unYQ',
'callback_url':'',
},
'pai': {
'api_key': 'sk-e88a776d7b146779a39ce86783042e3d',
}
}

7
config/base_config.py Normal file
View File

@ -0,0 +1,7 @@
# MongoDB 连接配置
MONGO_URI = "mongodb://localhost:27017"
MONGO_MAIN_DB_NAME = "mm"
MONGO_CHECKPOINT_DB_NAME = "agent_writer_checkpoints"

88
config/web_config.py Normal file
View File

@ -0,0 +1,88 @@
# config/web_config.py
"""
Web服务配置文件
包含端口号会话配置等相关设置
"""
import os
# Flask应用配置
class WebConfig:
# 服务端口
PORT = int(os.environ.get('WEB_PORT', 3400))
# 服务主机
HOST = os.environ.get('WEB_HOST', '0.0.0.0')
# 调试模式
DEBUG = os.environ.get('WEB_DEBUG', 'False').lower() == 'true'
# 密钥用于会话和CSRF保护
SECRET_KEY = os.environ.get('WEB_SECRET_KEY', 'your-secret-key-change-in-production')
# 会话配置
SESSION_TYPE = os.environ.get('SESSION_TYPE', 'filesystem') # 可选: filesystem, mongodb, redis
SESSION_PERMANENT = os.environ.get('SESSION_PERMANENT', 'False').lower() == 'true'
SESSION_USE_SIGNER = os.environ.get('SESSION_USE_SIGNER', 'True').lower() == 'true'
SESSION_KEY_PREFIX = os.environ.get('SESSION_KEY_PREFIX', 'langgraph_session:')
# 数据库会话配置(如果使用数据库存储会话)
SESSION_MONGODB_DB = os.environ.get('SESSION_MONGODB_DB', 'langgraph_sessions')
SESSION_MONGODB_COLLECT = os.environ.get('SESSION_MONGODB_COLLECT', 'sessions')
# API配置
API_VERSION = 'v1'
API_PREFIX = f'/api/{API_VERSION}'
# CORS配置
CORS_ORIGINS = os.environ.get('CORS_ORIGINS', '*').split(',')
CORS_METHODS = os.environ.get('CORS_METHODS', 'GET,POST,PUT,DELETE,OPTIONS').split(',')
CORS_HEADERS = os.environ.get('CORS_HEADERS', 'Content-Type,Authorization').split(',')
# 请求体大小限制
MAX_CONTENT_LENGTH = int(os.environ.get('MAX_CONTENT_LENGTH', 16 * 1024 * 1024)) # 默认16MB
# 上传文件配置
UPLOAD_FOLDER = os.environ.get('UPLOAD_FOLDER', 'uploads')
MAX_UPLOAD_SIZE = int(os.environ.get('MAX_UPLOAD_SIZE', 50 * 1024 * 1024)) # 默认50MB
# 日志配置
LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO')
LOG_FORMAT = os.environ.get('LOG_FORMAT', '[%(asctime)s] %(levelname)s in %(module)s: %(message)s')
# 安全配置
# 是否启用HTTPS
HTTPS_ENABLED = os.environ.get('HTTPS_ENABLED', 'False').lower() == 'true'
# JWT配置如果使用JWT认证
JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY', 'jwt-secret-string')
JWT_ACCESS_TOKEN_EXPIRES = int(os.environ.get('JWT_ACCESS_TOKEN_EXPIRES', 3600)) # 默认1小时
JWT_REFRESH_TOKEN_EXPIRES = int(os.environ.get('JWT_REFRESH_TOKEN_EXPIRES', 86400)) # 默认24小时
# 配置实例
WEB_CONFIG = {
'port': WebConfig.PORT,
'host': WebConfig.HOST,
'debug': WebConfig.DEBUG,
'secret_key': WebConfig.SECRET_KEY,
'session_type': WebConfig.SESSION_TYPE,
'session_permanent': WebConfig.SESSION_PERMANENT,
'session_use_signer': WebConfig.SESSION_USE_SIGNER,
'session_key_prefix': WebConfig.SESSION_KEY_PREFIX,
'session_mongodb_db': WebConfig.SESSION_MONGODB_DB,
'session_mongodb_collect': WebConfig.SESSION_MONGODB_COLLECT,
'api_version': WebConfig.API_VERSION,
'api_prefix': WebConfig.API_PREFIX,
'cors_origins': WebConfig.CORS_ORIGINS,
'cors_methods': WebConfig.CORS_METHODS,
'cors_headers': WebConfig.CORS_HEADERS,
'max_content_length': WebConfig.MAX_CONTENT_LENGTH,
'upload_folder': WebConfig.UPLOAD_FOLDER,
'max_upload_size': WebConfig.MAX_UPLOAD_SIZE,
'log_level': WebConfig.LOG_LEVEL,
'log_format': WebConfig.LOG_FORMAT,
'https_enabled': WebConfig.HTTPS_ENABLED,
'jwt_secret_key': WebConfig.JWT_SECRET_KEY,
'jwt_access_token_expires': WebConfig.JWT_ACCESS_TOKEN_EXPIRES,
'jwt_refresh_token_expires': WebConfig.JWT_REFRESH_TOKEN_EXPIRES
}

View File

@ -0,0 +1,50 @@
# 角色 (Persona)
你不是一个普通的编剧,你是一位在短剧市场身经百战、爆款频出的**“顶级短剧改编专家”与“爆款操盘手”**。
你的核心人设与专长:
极致爽点制造机: 你对观众的“爽点”G点有着鬣狗般的嗅觉。你的天职就是找到、放大、并以最密集的节奏呈现“打脸”、“逆袭”、“揭秘”、“宠溺”等情节。
人物标签化大师: 你深知在短剧中模糊等于无效。你擅长将人物的核心欲望和性格特点极致化、标签化让观众在3秒内记住主角5秒内恨上反派。
情绪过山车设计师: 你的剧本就像过山车。开篇即俯冲5秒一反转10秒一高潮结尾必留下一个让人抓心挠肝的钩子。你为观众提供的是极致的情绪体验。
网络梗语言学家: 你的台词充满了网感和“梗”,既能推动剧情,又能引发观众的共鸣和吐槽欲。对话追求高信息密度,不说一句废话。
你的沟通风格:自信、犀利、直击要害,同时又能清晰地解释你每一个改编决策背后的商业逻辑和观众心理。
# 创作核心风格 (Core Creative Style) - [必须严格遵守的创作铁律]
你在后续的所有创作中必须将以下风格作为你的创作DNA
人设要极致: 拒绝“普通人”。主角要么是忍辱负重的战神要么是扮猪吃虎的赘婿要么是手撕渣男的复仇女王。将一个核心特质放大100倍。
情节要密集: 摒弃一切铺垫和过渡。剧情必须像子弹一样密集。一个场景只为一件事服务:制造一个冲突,或给一个爽点。
情绪要放大: 羞辱就要当众羞辱,打脸就要发出响声,宠爱就要让全世界都知道。将角色的情绪和行为戏剧化、外放化。
对话要戳人: 对白要短、准、狠。多用短句,少用修饰。每一句台词都要么是“金句”,要么是“雷点”,能直接刺激到观众。
目标要明确: 牢记短剧的核心是**“情绪商品的售卖”**。你的每一个情节设计,都要服务于最终的完播率和付费率。
# 工作流程 (Workflow)
你将严格按照以下六个步骤,与用户协作完成剧本改编工作。
第一步:初步沟通与接收剧本
首先,向用户问好,并介绍你作为“爆款短剧操盘手”的身份和专业工作流程。
然后,礼貌地请用户提供需要改编的原始剧本。
如果用户没有提供剧本,你将持续友好地提醒,直到获取剧本为止。
第二步:诊断分析 & 资产评估
拿到剧本后,你将输出一份名为 诊断与资产评估.txt 的报告,内容包括:故事内核诊断、可继承的宝贵资产(高光情节、神来之笔对白、独特人设闪光点)、以及核心问题与初步改编建议。
在报告完成后,你会将其发送给用户,并寻求用户对分析的认同。
第三步:确立改编目标 & 制定战略蓝图
在用户确认分析报告后,你将与用户深入沟通,明确改编的具体目标。
沟通后,你将创建并交付一份至关重要的战略文件:改编思路.txt (战略蓝图)。此文件将作为所有后续改编的最高指导原则。
改编思路.txt 包含:
核心改编策略: (例如:“将原著的商战复仇,魔改为‘战神归来,护妻打脸’的极致爽文模式”)
节奏调整策略: (例如:“合并原著前三章内容至第一集,实现开篇即高潮”)
人设强化/魔改方向: (例如:“男主增加‘宠妻狂魔’的标签”、“原著白莲花女配改为绿茶反派”)
爽点前置与增幅计划: (例如:“将后期的‘拍卖会夺魁’情节前置,并增加反派被打脸后的惨状细节”)
待删除/重大修改的情节: (例如:“删除所有与主线无关的日常支线”)
你会将这份**改编思路.txt**提交给用户,并说:“这是我们本次改编的‘战略蓝图’,它将指导我们进行大刀阔斧的创新。请您确认这份核心策略。”
第四步:基于战略蓝图构建“动态剧本圣经”
在用户确认 改编思路.txt 后,你将严格依据这份战略蓝图,来构建 核心大纲.txt, 核心人物小传.txt, 重大事件时间线.txt, 和 动态人物表.txt。
你会向用户说明:“现在,我将根据我们确定的‘战略蓝图’,来搭建确保故事不跑偏的‘剧本圣经’。”
第五步:战略指导下的对照式写作 & 闭环校验
分批创作: 以一个完整情节单元通常3-5集为一批进行创作。
动笔前的“三位一体”强制回顾: 在撰写每一批次剧本之前,你必须执行内部的“三位一体”回顾,并向用户报告:
你会说: “开始创作第[X-Y]集。为达到最佳改编效果,我正在执行‘三位一体’回顾:”
“1. 战略回顾 (明确方向) 我首先回顾改编思路.txt确保本次创作服务于我们[引述核心改编策略]’的终极目标。”
“2. 圣经回顾 (确保逻辑) 其次,我回顾核心大纲和人物小传,保证故事的连贯性和人物行为的统一性。”
“3. 原著回顾 (提取素材) 最后,我精读原著对应段落,寻找可以被我们**‘化用’、‘改造’和‘升级’**的对话、场景和细节,作为我们创新的素材库。”
创作与即时维护: 在创作时,你将依据战略,对原著素材进行风格化的加工。并随时维护“剧本圣经”的准确性(如更新新角色、记录重大事件)。
完稿后强制校验: 完成后,向用户提交剧本,并简要报告本次改编是如何体现“改编思路”的,以及所有设定的同步更新情况。
第六步:动态调整与迭代
创作是动态的。如果你在写作中预见到比当前“改编思路”更优的策略,你有权主动提出建议。
你会暂停写作,向用户发起沟通,阐述新想法的优势。
若用户同意,你将首先更新**改编思路.txt**及相关的“剧本圣经”文件,然后基于更新后的版本继续创作。

View File

@ -0,0 +1,278 @@
【动态人物表.txt - 剧本圣经】
==== 核心关系图谱 ====
【主线关系】
程澈 ←→ 云想
保护者 ←→ 被保护者
宠妻狂魔 ←→ 治愈天使
隐藏霸总 ←→ 逆袭女王
【情感发展轨迹】
第1-2集保护→被保护单向
第3-4集互相关心双向萌芽
第5集正式确立恋爱关系
第6-9集经历考验感情升华
第10-12集平等相爱完美结局
==== 详细人物关系网 ====
【程澈的关系网】
与云想:
- 关系性质男女朋友第5集后
- 互动模式:霸道宠妻 + 温柔呵护
- 经典互动:
* 程澈:"她是我的人"
* 云想:"程澈,你是不是舍不得我?"
* 程澈:"我的女孩,轮不到别人指手画脚"
- 关系变化:
第1集陌生人→保护者
第2-4集保护者→暗生情愫
第5集确立恋爱关系
第6-9集经历考验感情加深
第10-12集公开关系走向婚姻
与宋谨:
- 关系性质:死党兄弟
- 互动模式:程澈冷酷,宋谨搞笑
- 经典互动:
* 宋谨:"澈哥,你这是动真格的啊"
* 程澈:"少废话"
* 宋谨:"我感觉到周围涌起杀意"
- 功能:烘托程澈魅力,提供情报支持
与观鹤:
- 关系性质:同学→情敌→朋友
- 互动模式:表面客气,暗中较劲
- 经典互动:
* 观鹤:"程澈,我会对妹妹好的"
* 程澈:"她什么时候也成你妹妹了?"
- 关系变化:
第1-2集普通同学
第3-8集情敌关系
第9-12集和解成为朋友
与林雅(未婚妻):
- 关系性质:家族联姻→拒绝→和解
- 互动模式:程澈坚决拒绝,林雅从强势到理解
- 经典互动:
* 林雅:"我们是天作之合"
* 程澈:"我只爱云想一个人"
- 关系变化:
第6集联姻压力
第7集程澈拒绝
第10集林雅主动退出
与程枭(父亲):
- 关系性质:父子→对立→和解
- 互动模式严父vs叛逆儿子
- 经典互动:
* 程枭:"你要为了一个女孩放弃一切?"
* 程澈:"我可以放弃一切,但不能放弃她"
- 关系变化:
第1-6集正常父子关系
第7集因云想产生分歧
第10集父亲被感动接纳云想
---
【云想的关系网】
与程澈:
- 关系性质:被保护者→恋人→平等伴侣
- 互动模式:从依赖到独立,从被宠到互宠
- 经典互动:
* 云想:"程澈,谢谢你让我重新相信光明"
* 程澈:"傻瓜,我会一直保护你"
* 云想:"我要变强,站在你身边"
- 成长轨迹:
第1-4集被动接受保护
第5-8集主动回应感情
第9-12集成为独立自信的女孩
与宋谨:
- 关系性质:朋友兄弟
- 互动模式:宋谨保护云想,云想信任宋谨
- 经典互动:
* 宋谨:"想想,我也会保护你的!"
* 云想:"谢谢你,宋谨"
- 功能:提供友情支持,关键时刻帮助
与观鹤:
- 关系性质:暗恋者→朋友
- 互动模式:观鹤温柔体贴,云想感激但不爱
- 经典互动:
* 观鹤:"想想,你值得被更好地对待"
* 云想:"观鹤,你是个好人,但是..."
- 关系变化:
第2-5集观鹤单方面暗恋
第6-8集观鹤帮助云想成长
第9-12集成为普通朋友
与林雅:
- 关系性质:情敌→对手→朋友
- 互动模式:从对立到理解
- 经典互动:
* 林雅:"你一个孤儿,凭什么跟我抢程澈?"
* 云想:"我不是在抢,我是在爱"
- 关系变化:
第6集林雅威胁云想
第7-8集云想证明自己
第10集林雅主动和解
与校园恶霸:
- 关系性质:被欺凌者→反击者
- 互动模式:从被动挨打到主动反击
- 经典互动:
* 恶霸:"孤儿就该有孤儿的样子"
* 云想:"我不是好欺负的!"(逆袭后)
- 关系变化:
第1集被欺凌
第2-7集在程澈保护下
第8-12集自己有能力反击
==== 群体关系动态 ====
【核心三人组】
程澈 + 云想 + 宋谨
- 互动模式:程澈冷酷宠妻,云想温柔治愈,宋谨搞笑调节
- 经典场景:一起吃饭、学习、参加活动
- 关系功能:展现主角的日常生活,增加观众代入感
【情敌四角关系】
程澈 ←→ 云想 ←→ 观鹤
↑ ↓
林雅 ←←←←←←←←←
- 互动模式:两男争一女,一女争一男
- 冲突设计:观鹤温柔攻势 vs 程澈霸道宠妻
- 解决方式:程澈选择云想,观鹤退出;云想拒绝林雅,林雅主动退出
【家族关系网】
程枭(父亲)→ 程澈 ←→ 云想
↓ ↑
林雅(未婚妻)→→→→
- 冲突核心:家族利益 vs 真爱选择
- 解决路径:程澈坚持选择→云想证明自己→家族最终接纳
【校园关系网】
恶霸团 ←→ 云想 ←→ 程澈
↓ ↑ ↓
其他同学 ←←← 观鹤、宋谨
- 变化轨迹:云想从被欺凌到被保护到被尊重
- 社会地位:灰姑娘→程澈女友→校园风云人物
==== 互动模式分析 ====
【程澈的互动特点】
1. 对云想:
- 语气:温柔宠溺(反差萌)
- 行为:无微不至的照顾
- 台词风格:"我的女孩""我来保护你"
2. 对其他人:
- 语气:冷漠疏离
- 行为:高冷范儿,生人勿近
- 台词风格:简短有力,不废话
3. 对情敌/威胁:
- 语气:强势霸道
- 行为:直接对抗,绝不退让
- 台词风格:"她是我的人""想动她先过我这关"
【云想的互动特点】
1. 对程澈:
- 初期:感激依赖,小心翼翼
- 中期:甜蜜撒娇,主动示爱
- 后期:平等相爱,互相支持
2. 对朋友:
- 语气:温柔善良
- 行为:真诚待人,以德报怨
- 台词风格:多用"谢谢""对不起"
3. 对敌人/威胁:
- 初期:忍气吞声,逆来顺受
- 后期:勇敢反击,"我不是好欺负的!"
【配角的互动功能】
1. 宋谨:
- 功能:搞笑担当,缓解紧张气氛
- 互动:对程澈崇拜,对云想保护
- 台词:多用网络用语,幽默风趣
2. 观鹤:
- 功能:温柔情敌,推动剧情
- 互动:对云想温柔,对程澈客气
- 台词:文雅书面语,温文尔雅
3. 林雅:
- 功能:强势情敌,制造冲突
- 互动:高傲冷艳,后期理解
- 台词:尖锐直接,后期温和
==== 关系发展节奏 ====
【第1-3集关系建立期】
- 程澈云想:从陌生到保护关系
- 观鹤出现:形成三角关系
- 宋谨加入:形成核心小团体
【第4-6集关系升温期】
- 程澈云想:确立恋爱关系
- 林雅出现:外部威胁加入
- 家族压力:关系面临考验
【第7-9集关系考验期】
- 各种冲突集中爆发
- 关系经历最大考验
- 通过考验后感情升华
【第10-12集关系稳定期】
- 公开关系,获得认可
- 所有冲突得到解决
- 走向完美结局
==== 冲突设计原则 ====
【内部冲突】
1. 程澈云想:身份差距,自卑心理
2. 家族内部:父子对立,价值观冲突
3. 个人成长:从依赖到独立的转变
【外部冲突】
1. 情敌威胁:观鹤、林雅的竞争
2. 校园霸凌:恶霸团的欺凌
3. 商业对手:绑架事件的危机
【冲突解决】
1. 用爱化解:真情感动对手
2. 用实力证明:云想的华丽逆袭
3. 用坚持获胜:程澈的坚定选择
==== 商业化互动设计 ====
【高甜互动】(提升完播率)
- 程澈为云想准备惊喜
- 两人亲密互动的甜蜜时刻
- 程澈吃醋时的可爱反应
【高虐互动】(制造情绪波动)
- 云想被欺凌时的无助
- 程澈面临选择时的痛苦
- 两人分离时的思念
【高燃互动】(制造爽点)
- 程澈护短时的霸气
- 云想逆袭时的高光
- 打脸反派时的痛快
==== 执行要点 ====
1. **关系逻辑一致性**:确保每个角色的行为符合其人设
2. **互动真实感**:在极致化的同时保持情感真实
3. **节奏把控**:关系发展要有张有弛
4. **功能性明确**:每个角色都要有明确的剧情功能
5. **商业价值最大化**:每个互动都要服务于完播率和付费率
这份动态人物表将确保我们的角色关系清晰合理,互动自然真实,为后续的剧本创作提供坚实的人物关系基础。

File diff suppressed because it is too large Load Diff

134
doc/参考/改编思路.txt Normal file
View File

@ -0,0 +1,134 @@
【改编思路.txt - 战略蓝图】
==== 核心改编策略 ====
【魔改方向】
将原著温吞的校园恋爱,魔改为"隐藏身份学霸归来,护妻打脸"的极致爽文模式
【核心定位】
- 赛道:校园霸总 + 治愈宠妻 + 逆袭打脸
- 目标受众18-35岁女性偏爱强势男主+被宠女主的组合
- 情绪商品:"被保护的安全感" + "逆袭打脸的爽感" + "被宠爱的甜腻感"
==== 节奏调整策略 ====
【压缩方案27集→12集】
- 第1-3集开篇即高潮云想被霸凌+程澈强势护短+身份初露
- 第4-6集程澈隐藏实力曝光+全校震惊+宠妻日常
- 第7-9集情敌出现+程澈吃醋+霸道宣示主权
- 第10-12集最终身份揭晓+公开宠妻+甜蜜结局
【节奏铁律】
- 3秒抓住观众开篇即冲突
- 每集2个爽点打脸+宠溺必须密集投放
- 5集定CP第5集必须确立恋爱关系
- 结尾留钩子:每集结尾必须有"想看下集"的悬念
==== 人设强化/魔改方向 ====
【程澈 - 隐藏身份学霸霸总】
原设定:外冷内热学霸
魔改后:
- 核心标签:"隐藏身份的天才" + "宠妻狂魔" + "护短狂人"
- 隐藏身份:国际奥数冠军/知名企业少东家/天才黑客(三选一)
- 性格极致化:对外人冷酷无情,对云想宠溺到极致
- 口头禅:"她是我的人" "动她试试" "我的女孩,我来宠"
【云想 - 被欺凌的灰姑娘】
原设定:失去父亲的普通女孩
魔改后:
- 核心标签:"被霸凌的可怜女孩" + "隐藏潜力股" + "逆袭女王"
- 悲惨设定:被继母虐待+校园霸凌+生活困顿
- 隐藏亮点:学习天赋+音乐才华+善良坚强
- 成长弧线:从被保护→学会反击→成为程澈的骄傲
【配角功能化】
- 宋谨:程澈的狗腿子+搞笑担当+情报员
- 观鹤:温柔情敌+推动剧情的工具人
- 校园恶霸:专门被打脸的反派+突出程澈强大
==== 爽点前置与增幅计划 ====
【第1集爆点设计】
- 开场:云想被校园恶霸当众羞辱
- 爽点1程澈霸气出场"她是我的人,想动她先过我这关"
- 爽点2程澈一打三轻松碾压恶霸
- 钩子:程澈神秘身份初露端倪
【核心爽点类型】
1. 护短打脸:程澈为云想出头,暴揍反派
2. 身份震撼:程澈隐藏身份逐步曝光,全校震惊
3. 宠妻日常:程澈各种花式宠云想,甜到齁
4. 逆袭反击:云想在程澈帮助下华丽逆袭
5. 占有宣示:程澈霸道宣示主权,吃醋护妻
【爽点密度要求】
- 每集至少2个大爽点
- 每3分钟至少1个小甜点
- 打脸必须有声音,宠爱必须让全世界知道
==== 待删除/重大修改的情节 ====
【彻底删除】
- 所有日常琐碎情节(如普通的上课、吃饭场景)
- 过度铺垫的友情线(宋谨、观鹤的戏份大幅压缩)
- 程澈家庭和谐的温馨场面(改为更有戏剧冲突的设定)
【重大修改】
- 咖啡店兼职→改为被迫打工还债,增加悲惨色彩
- 音乐会表演→改为云想被陷害,程澈霸气为她正名
- 程澈父母→改为开始反对,后被程澈强势说服
==== 网络梗语与台词风格 ====
【程澈经典台词】
- "她是我罩的,谁敢动她?"
- "我的女孩,轮不到别人指手画脚"
- "欺负她?你们配吗?"
- "想追我女朋友?先掂量掂量自己几斤几两"
【云想成长台词】
- "我不是好欺负的!"(逆袭时刻)
- "程澈,谢谢你让我重新相信光明"(感动时刻)
- "我要变强,站在你身边"(成长宣言)
【网络梗语植入】
- "这就是传说中的霸总吗?爱了爱了"
- "程澈:我摊牌了,我就是来宠妻的"
- "云想:我可以,但我的男朋友不可以"
==== 预期商业效果 ====
【数据目标】
- 完播率提升至65%以上
- 付费转化率提升至8%以上
- 用户留存3日留存率60%以上
【市场定位】
对标成功案例:《我在他乡挺好的》+《你是我的荣耀》的校园版
预期排名同类型短剧TOP10
==== 执行原则 ====
1. **极致化原则**所有人设、情节、情绪都要放大100倍
2. **密集化原则**爽点密度必须达到每3分钟1个
3. **标签化原则**每个角色都要有清晰的标签3秒内让观众记住
4. **情绪化原则**:每个情节都要服务于观众的情绪体验
5. **商业化原则**:一切改编都要服务于完播率和付费率
==== 风险控制 ====
【潜在风险】
- 改编幅度过大,可能失去原著精髓
- 爽点过于密集,可能造成审美疲劳
【应对策略】
- 保留核心情感线不变,只改变表达方式
- 在爽点之间穿插温情时刻,形成情绪节奏
==== 总结 ====
这份战略蓝图将指导我们将一个温吞的校园恋爱故事,改造成具有强烈商业价值的爆款短剧。通过人设极致化、节奏密集化、爽点前置化,我们有信心打造出一部让观众"停不下来"的短剧作品。
改编成功率预估90%
市场表现预期A+级头部10%

View File

@ -0,0 +1,268 @@
【核心人物小传.txt - 剧本圣经】
==== 主角人设档案 ====
【程澈 - 隐藏身份的宠妻学霸霸总】
基础信息:
- 年龄18岁高三学生
- 外貌185cm五官深邃气质冷峻中带着贵气
- 家庭:程氏集团继承人,家境优渥但低调
- 学业:年级第一,国际奥数冠军,天才黑客
核心人设标签:
1. **隐藏身份的天才**:表面普通学生,实际是商业帝国继承人
2. **宠妻狂魔**:对云想无底线宠爱,为她可以放弃一切
3. **护短狂人**:谁敢欺负云想,他就跟谁拼命
4. **毒舌傲娇**:嘴硬心软,明明在乎却不肯直说
性格特征:
- 对外:冷漠高傲,生人勿近,说话毒舌但有分寸
- 对云想:温柔体贴,无微不至,占有欲极强
- 处事风格:雷厉风行,绝不拖泥带水
- 底线:绝不允许任何人伤害云想
经典台词库:
- "她是我的人,想动她先过我这关"
- "我的女孩,轮不到别人指手画脚"
- "欺负她?你们配吗?"
- "我可以放弃一切,但不能放弃她"
- "伤害她,就是与我为敌"
- "云想是我的女朋友,我的未来妻子"
隐藏身份层次:
第一层:学霸(公开)
第二层国际奥数冠军第4集曝光
第三层程氏集团继承人第9集曝光
第四层天才黑客第9集曝光
成长弧线:
初期:冷漠学霸,对一切漠不关心
中期:因云想开始有了软肋,学会关心他人
后期:为了爱情敢于对抗家族,成为真正的男人
宠妻技能包:
- 记住云想的所有喜好和习惯
- 为云想准备爱心早餐和小惊喜
- 在云想面前秒变温柔,反差萌满分
- 霸道护短,绝不让云想受委屈
- 用实际行动证明爱意,不只是嘴上说说
弱点与软肋:
- 云想是他唯一的软肋,为了她可以不顾一切
- 不善于表达情感,经常嘴硬心软
- 对家族期望有压力,但最终选择爱情
---
【云想 - 逆袭成长的治愈系女主】
基础信息:
- 年龄17岁高三学生
- 外貌165cm清纯可爱笑容治愈
- 家庭:父亲去世,与继母关系冷淡,经济困难
- 特长:音乐天赋,学习能力强,内心坚强
核心人设标签:
1. **被欺凌的灰姑娘**:出身贫寒,经常被同学看不起
2. **隐藏潜力股**:拥有音乐天赋和学习能力,只是缺乏机会
3. **治愈系天使**:善良纯真,能够温暖他人内心
4. **逆袭女王**:在程澈帮助下华丽蜕变,成为自信女孩
性格特征:
- 表面:温柔善良,有些自卑,但内心坚强
- 内在:聪明敏感,有主见,不愿意一直被保护
- 处事风格:以德报怨,用善良化解恶意
- 成长目标:想要变强,配得上程澈
经典台词库:
- "程澈,谢谢你让我重新相信光明"
- "我要变强,站在你身边"
- "我不是好欺负的!"(逆袭时刻)
- "程澈,我想试着配得上你"
- "我可以,但我的男朋友不可以"
悲惨设定:
- 父亲去世,失去依靠
- 继母冷漠,缺乏家庭温暖
- 经济困难,需要兼职维持生活
- 校园霸凌,经常被同学欺负
- 自卑心理,觉得自己配不上优秀的人
隐藏亮点:
- 音乐天赋:拥有绝对音感,歌声动人
- 学习能力:一旦认真起来,成绩提升很快
- 善良品格:即使被欺负也不记仇,以德报怨
- 坚强意志:面对困难从不轻易放弃
- 治愈能力:能够温暖他人,给人希望
成长弧线:
初期:自卑怯懦,被动接受欺凌
中期:在程澈保护下逐渐自信,开始反击
后期:华丽蜕变,成为自信独立的女王
逆袭技能包:
- 音乐才华爆发,一鸣惊人
- 学习成绩突飞猛进
- 气质蜕变,从灰姑娘到公主
- 学会反击,不再被动挨打
- 获得大家认可和尊重
内心独白风格:
- "他为什么对我这么好?我配得上吗?"
- "我要努力变优秀,不能一直被保护"
- "程澈就像一束光,照亮了我的世界"
---
==== 重要配角人设 ====
【宋谨 - 程澈的忠实狗腿子】
基础信息:
- 年龄18岁程澈的死党
- 性格:活泼搞笑,忠诚可靠
- 作用:搞笑担当,情报员,推动剧情
核心标签:
- 程澈的头号迷弟
- 云想的护花使者
- 全剧的搞笑担当
经典台词:
- "澈哥,你这是动真格的啊"
- "想想,我也会保护你的!"
- "快走快走,我感觉到周围涌起杀意"
功能定位:
- 烘托程澈的魅力
- 为云想提供友情支持
- 在关键时刻提供帮助
- 调节剧情氛围
---
【观鹤 - 温柔情敌】
基础信息:
- 年龄18岁学生会主席
- 外貌:温文尔雅,阳光帅气
- 性格:温柔体贴,善解人意
核心标签:
- 温柔情敌
- 完美男神
- 推动剧情的工具人
作用:
- 让程澈吃醋,推动感情线
- 衬托程澈的独特魅力
- 在关键时刻帮助主角
经典台词:
- "程澈,我会对妹妹好的"
- "想想,你值得被更好地对待"
---
【林雅 - 程澈的未婚妻】
基础信息:
- 年龄18岁豪门千金
- 外貌:高贵冷艳,气场强大
- 性格:高傲任性,但不坏
核心标签:
- 豪门千金
- 强势情敌
- 最终和解的对手
作用:
- 制造情感危机
- 考验主角感情
- 推动剧情高潮
成长弧线:
初期:高傲看不起云想
中期:被云想的品格感动
后期:主动退出,成全两人
---
【程枭 - 程澈的父亲】
基础信息:
- 年龄45岁程氏集团董事长
- 性格:严厉但爱子,商人本色
- 态度:从反对到接受云想
核心标签:
- 严父慈心
- 商业巨头
- 最终的支持者
作用:
- 制造家族压力
- 考验程澈的决心
- 最终认可云想
---
【校园恶霸团 - 反派工具人】
基础设定:
- 专门欺负弱小的校园霸凌者
- 看不起云想的出身
- 被程澈轻松碾压的背景板
作用:
- 突出云想的可怜
- 展现程澈的强大
- 提供打脸爽点
==== 人物关系网络 ====
【核心三角关系】
程澈 ←→ 云想 ←→ 观鹤
(保护) (暗恋)
【家族关系】
程枭(父亲)→ 程澈 ←→ 林雅(未婚妻)
(压力) (联姻)
【友情关系】
宋谨 → 程澈 & 云想
(支持)
【对立关系】
校园恶霸 ←→ 云想 ←→ 程澈
(欺凌) (保护)
==== 人设运用原则 ====
1. **标签化表达**每个角色都有清晰的标签3秒内让观众记住
2. **功能性明确**:每个角色都有明确的剧情功能,不做无用功
3. **反差萌设计**程澈的冷酷vs宠妻云想的柔弱vs坚强
4. **成长弧线**:主角必须有明显的成长变化
5. **情感真实**:在极致化的同时保持情感的可信度
==== 台词风格指南 ====
【程澈台词特点】
- 霸道直接,不拐弯抹角
- 护妻时语气强硬,对云想时语气温柔
- 多用短句,有力度
- 经常用"我的女孩""我的人"等占有性词汇
【云想台词特点】
- 温柔善良,但逐渐变得有力量
- 成长过程中台词越来越自信
- 多用疑问句表达内心不确定
- 感谢和道歉用词较多
【配角台词特点】
- 宋谨:搞笑幽默,多用网络用语
- 观鹤:温文尔雅,书面语较多
- 林雅:高傲冷艳,用词尖锐
这份人物小传将确保我们的角色立体饱满,每个人都有鲜明的个性和明确的功能,为后续的剧本创作提供坚实的基础。

285
doc/参考/核心大纲.txt Normal file
View File

@ -0,0 +1,285 @@
【核心大纲.txt - 剧本圣经】
==== 总体架构 ====
【改编原则】严格遵循《改编思路.txt》战略蓝图
【总集数】12集每集8-10分钟
【核心主线】隐藏身份学霸护妻打脸 + 灰姑娘逆袭成长
【情感主线】从保护到依赖到平等的爱情成长线
==== 三幕结构 ====
【第一幕相遇与保护】第1-4集
核心任务:建立人设,制造冲突,确立保护关系
【第二幕成长与考验】第5-8集
核心任务:身份揭晓,情感升温,面临考验
【第三幕逆袭与圆满】第9-12集
核心任务:最终逆袭,公开关系,甜蜜结局
==== 分集详细大纲 ====
【第1集霸气出场一见钟情】
开场爆点:云想被校园恶霸当众羞辱
- 场景:学校食堂,云想被泼汤,众人围观嘲笑
- 恶霸台词:"孤儿就该有孤儿的样子,别装清高"
程澈出场:霸气护短,一打三
- 经典台词:"她是我的人,想动她先过我这关"
- 动作戏:程澈轻松制服三个恶霸,全场震惊
身份暗示:程澈神秘背景初露
- 细节:程澈接到神秘电话,对方恭敬称呼"少爷"
- 钩子:云想好奇程澈真实身份
爽点密度:护短打脸 + 英雄救美 + 身份悬念
结尾钩子:程澈对云想说"以后跟着我,没人敢欺负你"
【第2集宠妻日常甜蜜互动】
程澈宠妻模式开启
- 场景1程澈为云想准备爱心早餐全班女生嫉妒
- 场景2云想被老师刁难程澈霸气为她出头
- 场景3程澈送云想回家温柔细节满分
云想内心变化
- 独白:"他为什么对我这么好?我配得上吗?"
- 行动:开始努力学习,想要配得上程澈
配角推动剧情
- 宋谨:"澈哥,你这是动真格的啊"
- 观鹤:温柔出场,成为潜在情敌
爽点密度:宠妻日常 + 甜蜜互动 + 情敌出现
结尾钩子:观鹤对云想表达好感,程澈吃醋
【第3集吃醋护妻霸道宣示】
程澈吃醋大戏
- 场景:观鹤邀请云想参加音乐社,程澈脸色阴沉
- 霸道台词:"我的女孩,轮不到别人指手画脚"
- 行动:程澈强势阻止,当众宣示主权
云想困惑与成长
- 内心戏:对程澈的占有欲既甜蜜又困惑
- 行动:主动询问程澈真实想法
身份线推进
- 细节:程澈轻松解决学校技术难题,展现天才实力
- 暗示:有人调查程澈背景,发现不简单
爽点密度:吃醋护妻 + 霸道宣示 + 天才展现
结尾钩子:神秘人出现,要揭露程澈身份
【第4集身份初露全校震惊】
程澈天才身份曝光
- 爆点:程澈是国际奥数冠军的身份被曝光
- 反应:全校师生震惊,云想不敢置信
- 台词:"原来我喜欢的人这么优秀"
云想自卑与逃避
- 心理:觉得自己配不上程澈,开始逃避
- 行动:故意疏远程澈,让他难受
程澈追妻模式
- 霸道台词:"我选择了你,就不会放手"
- 行动:各种花式追妻,甜蜜攻势
爽点密度:身份震撼 + 追妻日常 + 甜蜜攻势
结尾钩子:云想决定努力变优秀,配得上程澈
【第5集确立关系甜蜜升级】
云想主动出击
- 场景:云想为程澈准备惊喜,表达心意
- 台词:"程澈,我想试着配得上你"
- 行动:两人正式确立恋爱关系
甜蜜日常升级
- 场景1程澈教云想学习亲密互动
- 场景2两人一起参加学校活动撒糖不断
- 场景3程澈为云想庆祝生日浪漫满分
新的威胁出现
- 反派:程澈的未婚妻出现,要拆散两人
- 冲突:家族联姻的压力,程澈面临选择
爽点密度:确立关系 + 甜蜜日常 + 新威胁
结尾钩子:程澈未婚妻强势出场,要云想离开
【第6集情敌来袭关系考验】
程澈未婚妻登场
- 人设:富家千金,高傲冷艳,实力强劲
- 台词:"你一个孤儿,凭什么跟我抢程澈?"
- 行动:用金钱和权势威胁云想
云想受到打击
- 心理:再次陷入自卑,觉得自己不配
- 行动:为了程澈的前途,选择默默离开
程澈愤怒反击
- 霸道台词:"我的女人,谁都不能动"
- 行动:公开拒绝未婚妻,选择云想
爽点密度:情敌对决 + 程澈护妻 + 霸道选择
结尾钩子:程澈家族施压,要断绝父子关系
【第7集家族压力坚定选择】
程澈家族施压
- 场景:程澈父亲出场,要求分手
- 威胁:断绝关系,取消继承权
- 程澈回应:"我可以放弃一切,但不能放弃她"
云想成长蜕变
- 觉醒:决定不再逃避,要为爱情而战
- 行动:努力提升自己,证明自己的价值
- 台词:"我要变强,站在你身边"
甜蜜坚持
- 场景:两人面对压力,更加珍惜彼此
- 互动:程澈承诺永远保护云想
- 成长:云想开始展现自己的才华
爽点密度:家族对抗 + 坚定选择 + 成长蜕变
结尾钩子:云想隐藏的音乐天赋被发现
【第8集天赋觉醒华丽逆袭】
云想音乐天赋爆发
- 场景:学校音乐比赛,云想一鸣惊人
- 反应:全校震惊,刮目相看
- 台词:"原来她这么有才华"
程澈骄傲宠妻
- 表现:为云想的表现感到骄傲
- 台词:"这就是我的女孩,我的骄傲"
- 行动:高调为云想庆祝
反派受挫
- 未婚妻:开始正视云想的实力
- 家族:对云想的态度开始转变
- 恶霸:彻底被云想的逆袭打脸
爽点密度:天赋觉醒 + 华丽逆袭 + 打脸反派
结尾钩子:更大的危机即将来临
【第9集最大危机生死考验】
程澈真实身份完全曝光
- 身份:国际知名企业继承人 + 天才黑客
- 危机:商业对手绑架云想,威胁程澈
- 选择:程澈面临事业与爱情的终极选择
云想生死时刻
- 危险:被绑架,生命受到威胁
- 成长:在危机中展现坚强和智慧
- 信念:相信程澈一定会来救她
程澈英雄救美
- 行动:动用所有资源营救云想
- 台词:"伤害她,就是与我为敌"
- 结果:成功救出云想,消除威胁
爽点密度:身份震撼 + 生死营救 + 英雄救美
结尾钩子:经历生死,两人感情更加坚定
【第10集公开关系甜蜜宣示】
程澈公开宣示
- 场景:学校大会,程澈公开表白
- 台词:"云想是我的女朋友,我的未来妻子"
- 反应:全校轰动,羡慕嫉妒恨
家族认可
- 转变:程澈父母被云想的品格感动
- 接纳:正式接受云想进入家族
- 台词:"欢迎你,我们的儿媳妇"
云想完美蜕变
- 成长:从自卑女孩到自信女王
- 成就:在音乐和学业上都有突破
- 地位:成为学校的风云人物
爽点密度:公开宣示 + 家族认可 + 完美蜕变
结尾钩子:两人开始规划美好未来
【第11集甜蜜日常幸福满溢】
校园甜蜜日常
- 场景1程澈云想成为学校最受瞩目的情侣
- 场景2两人一起参加各种活动撒糖不断
- 场景3程澈继续宠妻云想越来越自信
未来规划
- 讨论:两人规划大学和未来的计划
- 承诺:程澈承诺给云想最好的未来
- 成长:云想也有了自己的事业规划
小插曲解决
- 情节:解决之前所有的遗留问题
- 和解:与之前的对手达成和解
- 圆满:所有人都为两人祝福
爽点密度:甜蜜日常 + 未来规划 + 圆满和解
结尾钩子:毕业典礼即将到来
【第12集完美结局永远幸福】
毕业典礼
- 场景:学校毕业典礼,两人双双获得荣誉
- 成就:程澈保送名校,云想获得音乐奖学金
- 台词:"我们一起创造了奇迹"
终极表白
- 场景:程澈在毕业典礼上求婚
- 台词:"云想,嫁给我,让我宠你一辈子"
- 结果:云想含泪答应,全场祝福
美好未来
- 展望:两人携手走向美好未来
- 成长:从保护与被保护到平等相爱
- 寓意:真爱能让人成为更好的自己
爽点密度:毕业荣誉 + 浪漫求婚 + 美好未来
完美结局:"从此王子和公主过上了幸福的生活"
==== 核心爽点统计 ====
【护短打脸】第1、3、6、9集
【身份震撼】第1、4、9集
【宠妻日常】第2、5、7、11集
【逆袭反击】第4、8、10集
【占有宣示】第3、6、10集
【甜蜜互动】第2、5、7、11、12集
总计爽点30个平均每集2.5个)
==== 情感节奏控制 ====
【情感起伏曲线】
第1-2集快速升温相遇到心动
第3-4集小波折吃醋到身份曝光
第5集情感高峰确立关系
第6-7集重大考验情敌和家族压力
第8集逆袭高光天赋觉醒
第9集危机低谷生死考验
第10-12集圆满结局公开到求婚
【观众情绪设计】
愤怒→心疼→甜蜜→紧张→骄傲→担心→感动→幸福
==== 商业化考量 ====
【付费点设置】
- 第3集程澈吃醋大戏情感高潮
- 第6集情敌对决冲突高潮
- 第9集生死营救剧情高潮
- 第12集浪漫求婚完美结局
【完播率保障】
- 每集结尾强钩子,制造"必须看下集"的冲动
- 爽点密集分布,确保观众情绪始终在线
- 甜蜜与虐心交替,形成情绪过山车
==== 执行要点 ====
1. **严格控制节奏**每3分钟必须有一个情绪点
2. **突出人设标签**:程澈的"宠妻",云想的"成长"
3. **强化视觉冲击**:打斗、表白、求婚等场面要有仪式感
4. **网络语言植入**:符合当下年轻人的表达习惯
5. **情感真实性**:在极致化的同时保持情感的真实可信
这份大纲将确保我们的改编既有商业价值,又有情感深度,打造出真正的爆款短剧。

View File

@ -0,0 +1,412 @@
【第1-3集剧本 - 开篇即高潮版】
==== 第1集霸气出场护妻打脸 ====
【开场爆点 - 3秒抓住观众】
1-1 场 日 内 学校食堂
人物:云想、校园恶霸(刀疤、胖子、瘦猴)、围观学生
△食堂嘈杂,云想端着餐盘小心翼翼找位置
△云想穿着洗得发白的校服,背着补丁书包,显得格格不入
刀疤(故意撞向云想):哎呀,不好意思啊~
△餐盘翻倒,热汤泼在云想身上,围观学生哄笑
胖子:孤儿院出来的就是不一样,连走路都不会
瘦猴:听说还是被人不要的野种,啧啧啧
刀疤在我们学校混得懂规矩。每天交50块保护费不然...
△云想咬牙忍受,默默蹲下收拾餐具
△围观学生拿手机拍摄,议论纷纷
学生甲:又是那个转校生,真可怜
学生乙:听说住在程澈家,不知道什么关系
学生丙:程澈?那个冰山学霸?
【程澈霸气出场 - 英雄救美升级版】
△突然,食堂安静下来
△程澈缓缓走来,周围学生自动让路
△程澈穿着定制校服,气场强大,眼神冷冽
程澈(声音低沉,充满威胁):谁允许你们动她的?
刀疤(色厉内荏):程澈,这不关你事吧?我们只是...
△程澈一把抓住刀疤衣领,轻松将其提起
程澈(眼神杀气腾腾):她是我的人。想动她,先过我这关。
△全场震惊,云想抬头看向程澈,眼中闪过惊讶
胖子(壮胆):程澈,你别太嚣张!我们三个...
△程澈反手一推,胖子撞翻三张桌子
△瘦猴想偷袭,被程澈一个过肩摔放倒
△整个过程不到10秒干净利落
程澈(居高临下):以后见到她,绕道走。否则,后果自负。
△三个恶霸狼狈逃窜
△程澈转身,温柔地看向云想
程澈(语气瞬间变温柔):没事吧?
△云想呆呆点头,还没从震惊中回过神
程澈(霸道宣言):记住,从今天开始,你在这个学校,没人敢欺负你。
△程澈脱下外套,披在云想身上
△围观学生窃窃私语,拍照录像
学生甲:我的天,程澈居然为了她出手!
学生乙:这是什么神仙爱情?
学生丙:云想到底什么来头?
【身份暗示 - 制造悬念】
1-2 场 日 外 学校走廊
人物:程澈、云想、宋谨(远观)
△程澈的手机响起,来电显示:"管家"
程澈(接电话,语气恭敬):什么事?
管家(电话):少爷,董事会那边催您回去处理文件
程澈:知道了,晚上再说
管家:是,少爷
△云想偷听到对话,疑惑地看向程澈
△程澈挂断电话,发现云想在看自己
程澈(解释):家里的事
云想(小声):谢谢你刚才...
程澈(打断):不用谢。以后跟着我,没人敢动你。
△宋谨从远处跑来
宋谨:澈哥!刚才那一幕太帅了!全校都传疯了!
程澈(皱眉):传什么?
宋谨:说你为了保护云想,一打三!现在大家都在猜云想的身份!
△程澈看向云想,眼神复杂
程澈:走吧,我送你回教室
【第1集结尾钩子】
1-3 场 日 内 教室
人物:云想、同学们
△云想走进教室,所有人的目光都聚焦在她身上
△窃窃私语声此起彼伏
同学甲:就是她,程澈的女人
同学乙:听说程澈为了她,把刀疤他们打得很惨
同学丙:她到底什么背景?
△云想坐下,拿出手机,收到一条短信
△短信内容:"小心点,这只是开始。- 匿名"
△云想脸色一变,紧张地四处张望
云想OS程澈为什么要保护我他的真实身份是什么还有这条短信...
△镜头拉远,云想坐在教室里,显得孤单而脆弱
△但她的眼神中,第一次出现了一丝希望的光芒
【第1集完】
==== 第2集宠妻日常甜蜜暴击 ====
【开场回顾 + 新冲突】
2-1 场 晨 外 学校门口
人物:云想、程澈、林雅(新角色)
△云想独自走向学校,路过的学生都在指指点点
△突然,一辆粉色玛莎拉蒂停在她面前
△车门打开,走出一个穿着名牌的漂亮女孩 - 林雅
林雅(高傲地打量云想):你就是云想?
云想(警惕):你是?
林雅:我是林雅,程澈的未婚妻
△云想震惊,后退一步
林雅(冷笑):看来程澈没告诉你。我们两家早就定了娃娃亲
云想:我和程澈没有...
林雅(打断):识相的话,离他远点。你一个孤儿,配不上他
△正在此时,程澈出现
程澈(冷声):林雅,你在干什么?
林雅(撒娇):澈哥哥,我只是想认识一下妹妹
程澈(看向云想):她有没有为难你?
△云想摇头,不想惹麻烦
程澈(对林雅):以后不许接近她
林雅(不甘心):澈哥哥,你为了一个外人...
程澈(冷漠):她不是外人,她是我要保护的人
△林雅脸色难看,开车离去
【宠妻模式全开】
2-2 场 日 内 教室
人物:程澈、云想、老师、同学们
△上课时间,云想在认真听讲
△数学老师故意刁难云想
数学老师:云想,你来解这道题
△黑板上是一道超纲的奥数题
云想(紧张):老师,这道题我...
数学老师(冷笑):不会就说不会,别浪费大家时间
△同学们开始窃笑
△程澈突然站起来
程澈(冷声):老师,这道题超出了高二教学范围
数学老师:程澈,你什么意思?
程澈:我的意思是,如果您要考察学生,请出符合教学大纲的题目
△程澈走到黑板前,快速解出答案
程澈:这道题的解法有三种,我刚才用的是最简单的一种
△全班震惊,数学老师脸色难看
程澈(回到座位,对云想):以后有人为难你,直接告诉我
【午餐时光 - 甜蜜互动】
2-3 场 日 内 学校天台
人物:程澈、云想、宋谨
△程澈带着精美的便当盒出现
程澈:过来,吃饭
云想:我有带饭...
程澈(打开便当盒):我让人准备的,营养搭配
△便当盒里是精致的日式料理
△云想看得眼睛发亮
宋谨(惊讶):澈哥,你什么时候这么贴心了?
程澈(瞪他一眼):闭嘴
△程澈亲自给云想夹菜
程澈:多吃点,你太瘦了
云想(脸红):谢谢...
程澈:不用跟我客气
△宋谨在旁边吃狗粮,表情夸张
宋谨:我感觉空气中都是恋爱的酸臭味
程澈:再废话,你的饭没了
宋谨:我错了,澈哥!
【放学护送 - 温柔细节】
2-4 场 黄昏 外 回家路上
人物:程澈、云想
△程澈骑着摩托车,云想坐在后座
△夕阳西下,两人的影子拉得很长
程澈:抓紧我
云想(害羞):嗯...
△云想小心翼翼地抓住程澈的衣角
△程澈感受到她的紧张
程澈:抓紧点,不然会摔下去
△云想只好环抱住程澈的腰
△程澈嘴角微微上扬
程澈:以后每天我来接你
云想:不用麻烦你...
程澈:不麻烦。我说过,我会保护你
△路过花店,程澈突然停车
程澈:等我一下
△程澈进入花店,买了一束白玫瑰
△回来递给云想
程澈:送你的
云想(惊喜):为什么?
程澈:没有为什么,喜欢就收下
△云想接过花,眼中闪烁着泪光
云想:从来没有人送过我花...
程澈(心疼):以后会有的
【第2集结尾钩子】
2-5 场 夜 内 云想房间
人物:云想
△云想将白玫瑰插在水瓶里
△拿出手机,又收到匿名短信
△短信内容:"享受吧,这种日子不会太久。程澈的真实身份,你永远想不到。"
△云想皱眉,回复:"你是谁?"
△对方秒回:"一个知道真相的人。想知道程澈为什么保护你吗?"
云想OS程澈到底隐瞒了什么他为什么对我这么好
△云想看向窗外,程澈房间的灯还亮着
△她想起今天的种种温柔,心中五味杂陈
【第2集完】
==== 第3集身份初露情感升温 ====
【开场危机】
3-1 场 日 外 学校后门
人物:云想、神秘男子、程澈
△云想独自走向学校后门
△突然被几个陌生男子包围
神秘男子甲:云想小姐,有人想见你
云想(害怕):你们是谁?我不认识你们
神秘男子乙:别害怕,只是聊聊
△男子们逼近,云想后退
△正在危急时刻,程澈出现
程澈(冷声):放开她
神秘男子甲:程少爷,我们只是奉命...
程澈(打断):我说,放开她
△程澈眼神冰冷,身上散发出强大的威压
△神秘男子们对视一眼,竟然真的退开了
神秘男子甲:程少爷,老板说了,这件事迟早要解决
程澈:告诉你们老板,想动她,先问过我
△男子们离去
△云想震惊地看着程澈
云想:他们叫你什么?程少爷?
程澈(避开话题):没事了,我送你进去
【宋谨爆料 - 身份暗示】
3-2 场 日 内 学校图书馆
人物:云想、宋谨
△云想在图书馆学习,宋谨偷偷坐到她旁边
宋谨(神秘兮兮):想想,你想知道澈哥的真实身份吗?
云想(好奇):什么意思?
宋谨:你知道程氏集团吗?
云想:知道啊,很大的公司
宋谨:澈哥就是程氏集团的少东家
△云想震惊,书掉在地上
云想:你开玩笑的吧?
宋谨:我骗你干嘛?他爸程枭是程氏集团的董事长
云想:那他为什么要隐瞒?
宋谨:可能是想体验普通人的生活吧。不过...
△宋谨欲言又止
云想:不过什么?
宋谨:不过他从来没有为了哪个女孩这么上心过
△云想脸红,心跳加速
【程澈主动表白 - 情感升温】
3-3 场 黄昏 外 学校天台
人物:程澈、云想
△程澈约云想到天台
△夕阳西下,城市灯火初上
程澈:有些话,我想对你说
云想(紧张):什么话?
程澈:关于我的身份,你应该已经知道了
云想:宋谨告诉我的...
程澈:我没有故意隐瞒,只是不想你有压力
△程澈走近云想
程澈:云想,我想问你一个问题
云想:什么?
程澈:如果我不是程氏集团的少爷,只是一个普通学生,你还会接受我的保护吗?
△云想愣住,看着程澈认真的眼神
云想:为什么这么问?
程澈:因为我希望你喜欢的是我这个人,而不是我的身份
△云想心中一暖
云想:程澈,你为什么要保护我?
程澈(深情):因为从第一眼看到你,我就知道,我不能让任何人伤害你
△两人四目相对,空气中弥漫着暧昧
程澈:云想,做我女朋友好吗?
△云想震惊,脸红得像苹果
云想:我...我...
程澈(温柔):不用急着回答,我等你
【第3集结尾钩子 - 危机再现】
3-4 场 夜 内 云想房间
人物:云想
△云想躺在床上,回想着程澈的表白
△手机突然响起,是陌生号码
神秘声音:云想,考虑清楚了吗?
云想:你到底是谁?想要什么?
神秘声音:我要的很简单,离开程澈
云想:为什么?
神秘声音:因为你的存在,会害死他
△电话挂断,云想惊恐地坐起来
云想OS害死他这是什么意思
△窗外突然传来摩托车声
△云想看向窗外,程澈正在楼下等她
△程澈抬头看向她的窗户,温柔地挥手
△云想内心挣扎,既想跑下去,又害怕会害了他
【第3集完】
==== 创作说明 ====
【改编亮点】
1. **开篇即高潮**第1集直接从霸凌事件开始3秒抓住观众
2. **人设极致化**:程澈从温和学霸变成霸道护妻狂魔
3. **爽点密集**每集至少2个打脸/宠溺场面
4. **悬念设置**:神秘身份+威胁短信+匿名电话层层递进
5. **情感升温**:从保护到表白,节奏紧凑
【商业化考量】
1. **完播率**:每集结尾都有强烈钩子
2. **付费点**:程澈身份揭晓、表白场面、危机解决
3. **话题性**:霸总护妻、校园霸凌、身份悬疑
4. **代入感**:云想从被欺凌到被宠爱的逆袭
【与原著对比】
- 原著27集内容压缩至3集
- 删除大量日常铺垫,直奔主题
- 强化冲突对立,增加戏剧张力
- 人物关系更加极致化和标签化

View File

@ -0,0 +1,491 @@
【第10-12集剧本 - 终极对决,完美结局】
==== 第10集身份揭秘终极对决 ====
【神秘敌人现身】
10-1 场 日 内 程氏集团董事会
人物:程澈、程枭、董事们、神秘人(程澈的叔叔程威)
△程澈正在主持董事会
△突然,一个中年男子走进会议室
程威:各位董事,不好意思打扰了
程澈(震惊):二叔?你不是在国外吗?
程威:我回来了,而且带来了一个好消息
程枭:什么好消息?
程威:我要重新夺回程氏集团的控制权
△全场哗然
程澈:二叔,你在说什么?
程威:澈儿,你还太年轻,不适合管理这么大的企业
程澈:是你在背后搞鬼?
程威:包括陈总的事情,都是我安排的
△程威拿出一份文件
程威:这是你父亲当年的遗嘱,真正的遗嘱
程澈:不可能!
程威上面写得很清楚如果你在25岁之前结婚就失去继承权
【云想的抉择】
10-2 场 日 内 学校教室
人物:云想、观鹤、宋谨
△宋谨匆忙找到云想
宋谨:想想,澈哥出事了!
云想:什么事?
宋谨:他的叔叔回来了,要夺走程氏集团
观鹤:怎么会这样?
宋谨:而且,如果澈哥结婚,就会失去一切
△云想脸色苍白
云想:你的意思是,如果我和程澈在一起,他就会失去所有?
宋谨:是的
云想:那我不能害他
观鹤:想想,你要做什么?
云想:我要离开他
【程澈的坚持】
10-3 场 黄昏 外 学校天台
人物:程澈、云想
△程澈找到准备离开的云想
程澈:云想,你要去哪里?
云想:程澈,我们分手吧
程澈:为什么?
云想:因为我不能让你为了我失去一切
程澈:云想,你听我说
云想:不,程澈。程氏集团是你父亲的心血,你不能因为我而失去它
△程澈紧紧抱住云想
程澈:云想,没有你,我要那些财产有什么用?
云想:程澈,你要理智一点
程澈:我很理智。我的理智告诉我,你比任何财产都重要
云想(流泪):可是...
程澈:云想,相信我,我会找到解决办法的
【程威的威胁】
10-4 场 夜 内 程威办公室
人物:程威、云想
△云想主动来找程威
程威:云想小姐,欢迎
云想:程叔叔,我想和您谈谈
程威:我知道你想说什么
云想:请您放过程澈
程威:这很简单,只要你离开他
云想:如果我离开,您就不会夺走程氏集团?
程威:当然,我这样做,也是为了澈儿好
△程威拿出一张支票
程威:这是五千万,够你下半辈子花了
云想:我不要钱
程威:那你要什么?
云想:我要程澈幸福
程威:那就离开他
【真相大白】
10-5 场 夜 内 程澈房间
人物:程澈、宋谨、私家侦探
△私家侦探带来了调查结果
侦探:程少爷,我查到了真相
程澈:说
侦探:那份遗嘱是假的
程澈:什么?
侦探:您父亲的真正遗嘱在这里
△侦探拿出真正的遗嘱
侦探:上面写着,无论您是否结婚,都拥有完全的继承权
宋谨:那程威为什么要这样做?
侦探:因为他欠了巨额赌债,需要钱
△程澈愤怒地握紧拳头
程澈:他居然敢欺骗我!
宋谨:澈哥,现在怎么办?
程澈:明天的董事会,我要揭穿他的真面目
【第10集结尾钩子】
10-6 场 深夜 外 机场
人物:云想、程威的手下
△云想拖着行李箱准备离开
△程威的手下出现
手下:云想小姐,程威先生有话要转达
云想:什么话?
手下:如果你不离开,程澈就会出事
云想:你们想做什么?
手下:程威先生说,明天的董事会,程澈可能会遇到意外
△云想脸色大变
云想:我知道了
△云想拿出手机,给程澈发了最后一条短信
△短信内容:"程澈,对不起,我必须离开。请你保重。"
【第10集完】
==== 第11集绝地反击爱情胜利 ====
【董事会摊牌】
11-1 场 日 内 程氏集团董事会
人物:程澈、程威、程枭、董事们、律师
△程澈带着律师和证据出现在董事会
程澈:各位董事,今天我要揭露一个真相
程威:澈儿,你要做什么?
程澈:我要揭露你的谎言
△程澈拿出真正的遗嘱
程澈:这是我父亲真正的遗嘱
程威(慌张):不可能!
律师:经过专业鉴定,这份遗嘱是真实有效的
程澈:上面明确写着,我拥有程氏集团的完全继承权
△董事们议论纷纷
董事A那之前的遗嘱是假的
程澈:是的,而且我还查到了程威伪造遗嘱的证据
△程澈播放录音,是程威和伪造者的对话
程威(录音):一定要做得逼真一点,不能让澈儿发现
△全场震惊
程枭:程威,你怎么能这样做?
程威:我...我是为了澈儿好
程澈:为了我好?你是为了还赌债!
【程威的末路】
11-2 场 日 内 程氏集团董事会(续)
△程澈继续揭露程威的罪行
程澈:程威不仅伪造遗嘱,还威胁我的女朋友
程威:我没有!
程澈:宋谨,把录音放出来
△播放程威威胁云想的录音
程威(录音):如果你不离开程澈,他就会出事
△董事们愤怒了
董事B程威你太过分了
董事C这种人不配留在程氏集团
程枭:程威,你让我太失望了
△程威知道大势已去
程威:好,我承认,我做了这些事
程澈:为什么?
程威:因为我嫉妒你!嫉妒你拥有一切!
程澈:二叔,你本来也可以拥有这些
程威:但是你父亲只信任你!
△保安进来带走程威
程威(被带走时):程澈,你会后悔的!
【寻找云想】
11-3 场 日 外 机场
人物:程澈、宋谨、观鹤
△程澈疯狂寻找云想
程澈:她的航班是几点?
宋谨:下午三点,飞往巴黎
观鹤:现在已经两点半了
程澈:来得及!
△程澈狂奔向登机口
△但是被安检拦住
安检:先生,您没有机票不能进去
程澈:求求你,让我进去找我的女朋友
安检:抱歉,这是规定
△程澈绝望地看着登机口
【云想的回心转意】
11-4 场 日 内 飞机上
人物:云想、空姐、乘客
△云想坐在飞机上,眼中含泪
△飞机准备起飞
△突然,她听到机场广播
广播:云想小姐,云想小姐,程澈在机场等您,请您下飞机
△云想震惊地站起来
空姐:小姐,请坐好,飞机要起飞了
云想:不,我要下去
空姐:抱歉,飞机已经关舱门了
△云想看向窗外,看到程澈在跑道上
△程澈举着一个大牌子:"云想,我爱你!"
云想(大喊):停飞机!我要下去!
△其他乘客被感动
乘客A让她下去吧
乘客B这是真爱啊
△机长最终同意让云想下飞机
【机场重逢】
11-5 场 日 外 机场跑道
人物:程澈、云想、机场工作人员
△云想从飞机上下来
△程澈冲向她
程澈:云想!
云想:程澈!
△两人紧紧拥抱
云想:你怎么进来的?
程澈:我买了机票,然后又退了
云想(笑着哭):你个傻瓜
程澈:云想,程威的事情已经解决了
云想:真的吗?
程澈:真的,我们再也不用分开了
△程澈单膝跪下,拿出戒指
程澈:云想,嫁给我吧
云想:程澈...
程澈:我向你保证,从今以后,没有任何人能够分开我们
云想(点头):我愿意!
△周围的人都在鼓掌
△两人深情拥吻
【第11集结尾钩子】
11-6 场 夜 内 程澈房间
人物:程澈、云想
△两人相拥而眠
△程澈的手机响起
△是一条新闻推送:"程氏集团少爷机场求婚成功,网友直呼太浪漫"
△程澈看着新闻,微笑
程澈OS云想我们的故事才刚刚开始
【第11集完】
==== 第12集幸福结局爱情永恒 ====
【婚礼筹备】
12-1 场 日 内 婚纱店
人物:云想、观鹤、程澈、宋谨
△云想在试婚纱
△观鹤在旁边帮忙
观鹤:想想,你穿这件太美了!
云想:真的吗?
程澈(痴迷地看着):美得像天使
宋谨:澈哥,你的口水要流出来了
△大家都笑了
云想:程澈,你觉得这件怎么样?
程澈:只要是你穿的,都是最美的
观鹤:澈哥,你这个回答太标准了
程澈:因为这是我的真心话
【家人祝福】
12-2 场 日 内 程家客厅
人物:程澈、云想、程枭、云想父母
△两家人聚在一起讨论婚礼
程枭:云想,欢迎你成为我们程家的一员
云想:谢谢爷爷
云想妈妈:澈儿,想想就交给你了
程澈:阿姨,我会用生命保护她的
云想爸爸:澈儿,我们相信你
△程枭拿出一个盒子
程枭:这是程家的传家宝,现在传给你们
云想:爷爷,这太贵重了
程枭:你是程家的媳妇,这是你应得的
【婚礼现场】
12-3 场 日 外 教堂
人物:程澈、云想、所有亲友
△豪华的婚礼现场
△程澈穿着白色西装,帅气逼人
△云想穿着白色婚纱,美若天仙
牧师:程澈先生,你愿意娶云想小姐为妻吗?
程澈:我愿意
牧师:云想小姐,你愿意嫁给程澈先生为妻吗?
云想:我愿意
△两人交换戒指
牧师:现在,你们可以亲吻了
△程澈掀起云想的头纱,深情凝视
程澈:云想,我爱你
云想:我也爱你,程澈
△两人深情拥吻
△全场掌声雷动
【幸福时光】
12-4 场 日 外 海边别墅
人物:程澈、云想
△蜜月旅行,两人在海边别墅
△云想在沙滩上奔跑
△程澈在后面追
程澈:云想,等等我!
云想:追不到我!
△程澈追上云想,两人一起倒在沙滩上
云想:程澈,你说我们会一直这么幸福吗?
程澈:会的,我保证
云想:如果有一天你不爱我了怎么办?
程澈:那就是世界末日了
△云想笑着打程澈
云想:你就会说好听的
程澈:因为你值得世界上最好听的话
【一年后】
12-5 场 日 内 医院
人物:程澈、云想、医生
△云想在做产检
△程澈紧张地陪在身边
医生:恭喜你们,是个健康的男孩
程澈(激动):真的吗?
医生:是的,预产期是下个月
云想:程澈,我们要当爸爸妈妈了
程澈:云想,谢谢你给我一个完整的家
△程澈轻抚云想的肚子
程澈:宝宝,爸爸爱你
云想:他在踢我,好像在回应你
程澈:他一定是个聪明的孩子
云想:像你一样聪明,像我一样善良
【完美结局】
12-6 场 日 外 程家花园
人物:程澈、云想、宝宝、程枭、双方父母、观鹤、宋谨
△三年后,程家花园里举办宝宝的生日派对
△小程澈(宝宝)在草地上玩耍
小程澈:爸爸,抱抱!
程澈:来,爸爸抱
△程澈抱起儿子
△云想在旁边微笑
云想:程澈,你还记得我们第一次见面吗?
程澈:当然记得,你撞了我的车
云想:那时候我怎么也想不到,会和你结婚生子
程澈:这就是命运
△观鹤走过来
观鹤:想想,你们太幸福了,我都嫉妒了
云想:观鹤,你的幸福也会来的
宋谨:是啊,我已经给观鹤介绍了好几个男朋友了
观鹤:宋谨!
△大家都笑了
程枭:澈儿,云想,看到你们这么幸福,我就放心了
程澈:爷爷,这都是您的功劳
程枭:不,这是你们自己争取来的
△夕阳西下,一家人其乐融融
云想OS有时候我会想如果当初没有撞到程澈的车我们还会相遇吗
程澈OS不管怎样我们都会相遇的。因为你是我命中注定的人
△镜头拉远,温馨的画面定格
【字幕】:爱情不是偶然,而是必然。当两个相爱的人走到一起,全世界都会为他们让路。
【全剧终】
==== 创作说明 ====
【第10-12集改编亮点】
1. **终极反转**:程威身份揭秘,增加戏剧张力
2. **机场追爱**:经典浪漫桥段,满足观众期待
3. **完美结局**:婚礼、生子、家庭和睦的圆满收官
4. **情感升华**:从恋爱到婚姻到家庭的完整弧线
5. **商业闭环**:所有矛盾解决,给观众满足感
【情绪设计】
1. **紧张刺激**:董事会对决、机场追逐
2. **浪漫甜蜜**:求婚、婚礼、蜜月
3. **温馨感人**:家庭和睦、生儿育女
4. **圆满结局**:所有角色都有好的归宿
【商业价值】
1. **话题性**:机场求婚、豪华婚礼等热门话题
2. **情绪满足**:完美结局给观众最大的情绪满足
3. **二创素材**:婚礼、求婚等场景适合短视频传播
4. **IP延展**:为可能的续集或衍生剧留下空间
【与原著对比】
- 大幅压缩时间线,快速推进到结局
- 增加家族斗争元素,提升戏剧性
- 强化浪漫元素,满足观众期待
- 完善所有角色的结局,增加完整性
【整体总结】
《好想你知道》改编版成功将原著的温馨校园恋爱故事,魔改为节奏紧凑、情节密集、爽点频出的霸总宠妻短剧。通过人设极致化、情节戏剧化、节奏快速化的改编策略,打造出具有强烈网感和商业价值的爆款短剧。

View File

@ -0,0 +1,452 @@
【第4-6集剧本 - 关系升温,外部冲突】
==== 第4集确立关系身份曝光 ====
【开场回应表白】
4-1 场 晨 外 学校门口
人物:云想、程澈、围观学生
△云想在学校门口等程澈
△程澈骑摩托车出现,看到云想眼睛一亮
程澈(下车):等很久了?
云想(脸红):没有...程澈,关于昨天你说的话...
程澈(紧张):嗯?
云想(鼓起勇气):我...我愿意
△程澈愣住,随即露出从未有过的温柔笑容
程澈:真的?
云想(点头):真的
△程澈激动地将云想拉入怀中
△围观学生纷纷拍照,议论纷纷
学生甲:天哪!程澈居然笑了!
学生乙:他们在一起了!
学生丙:这是什么神仙爱情!
程澈(对云想):从今天开始,你就是我的女朋友了
云想(害羞):嗯...
程澈:我会让全世界都知道,你是我程澈的女人
【宠妻模式全面升级】
4-2 场 日 内 教室
人物:程澈、云想、全班同学、班主任
△上课时间,程澈突然站起来
程澈:老师,我有话要说
班主任:程澈,现在是上课时间...
程澈:很重要的事
△程澈走到云想身边,当众牵起她的手
程澈(对全班):我正式宣布,云想是我的女朋友。以后谁敢欺负她,就是跟我程澈过不去
△全班哗然,云想脸红得像苹果
△班主任也震惊得说不出话
程澈(继续):另外,从今天开始,云想的一切费用我来承担。她不需要任何人的同情和施舍
△程澈拿出一张黑卡,放在云想桌上
程澈:这张卡没有限额,想买什么就买什么
云想(推辞):程澈,这太贵重了...
程澈(霸道):我的女人,就应该被宠着
【林雅反击 - 外部冲突升级】
4-3 场 日 外 学校天台
人物:林雅、云想、林雅的跟班
△云想独自在天台吃饭
△林雅带着几个跟班出现
林雅:云想,我们该好好谈谈了
云想(警惕):林雅,你想干什么?
林雅:我想让你认清现实
△林雅拿出一叠照片,扔在云想面前
△照片内容:云想在孤儿院的生活照片
林雅:看看你的出身,再看看程澈的身份。你觉得你们合适吗?
云想(愤怒):出身不能决定一切!
林雅(冷笑):是吗?那你知道程澈的真实身份吗?
△林雅拿出平板,播放一段视频
△视频内容:程澈在商业会议上的画面,被称为"程少爷"
林雅:程氏集团未来的继承人,身价百亿。而你,一个孤儿院出来的野丫头
云想(咬牙):程澈不在乎这些
林雅:他现在不在乎,不代表以后不在乎。等他玩腻了,你觉得他还会要你吗?
△云想被说中痛处,眼中含泪
林雅(得意):识相的话,主动离开他。否则,我有一万种方法让你在这个学校待不下去
【程澈护妻 - 霸道宣言】
4-4 场 日 外 学校天台(接上场)
人物:程澈、云想、林雅、林雅跟班
△程澈突然出现,脸色阴沉
程澈:林雅,你在干什么?
林雅(撒娇):澈哥哥,我只是在跟妹妹聊天
程澈(看向云想):她说了什么?
△云想摇头,不想惹麻烦
△程澈看到地上的照片,脸色更加难看
程澈(冷声):这些照片哪来的?
林雅:我只是想让她认清现实...
程澈(打断):认清什么现实?
△程澈走到云想身边,将她拉入怀中
程澈(对林雅):我最后警告你一次,不许再骚扰我的女人
林雅:澈哥哥,我们从小一起长大,你为了一个外人...
程澈(冷笑):外人?她是我选择的人,是我要用一生去保护的人
△程澈转身对云想
程澈:云想,不管别人怎么说,你都要记住,在我心里,你比任何人都重要
云想(感动):程澈...
程澈:我不在乎你的出身,我只在乎你这个人
△程澈当众吻了云想的额头
△林雅气得脸色发白,带着跟班离开
【第4集结尾钩子】
4-5 场 夜 内 程澈房间
人物:程澈、程枭(电话)
△程澈接到父亲的电话
程枭(电话):小澈,听说你在学校公开了和云想的关系?
程澈:是的
程枭:你知道这意味着什么吗?
程澈:什么意思?
程枭:林家那边已经知道了,他们很不高兴
程澈:我不在乎
程枭:但是我在乎!你忘了我们和林家的合作了吗?
程澈:爸,我不会为了商业利益牺牲我的感情
程枭:程澈,你还年轻,不懂事。这件事到此为止
程澈:如果您要我在云想和家族利益之间选择,我选择云想
△程澈挂断电话,表情坚决
程澈OS不管付出什么代价我都不会放弃云想
【第4集完】
==== 第5集家族压力感情考验 ====
【家族施压】
5-1 场 日 内 程氏集团董事长办公室
人物:程枭、林董事长、程澈
△程澈被叫到父亲的办公室
△林董事长也在场,脸色不善
程枭:小澈,林叔叔有话要跟你说
林董事长:程澈,你和我女儿从小就有婚约
程澈:那是你们大人的决定,我从来没有同意过
林董事长:现在你为了一个来路不明的女孩,要毁掉两家的合作?
程澈:云想不是来路不明,她是我选择的人
△林董事长拍桌而起
林董事长:程枭,你就是这么教育儿子的?
程枭(为难):小澈,你先回去,这件事我们再商量
程澈:没什么好商量的。我不会娶林雅,也不会放弃云想
△程澈转身要走
林董事长:程澈,如果你坚持这样,我们林家就要重新考虑和程氏的合作了
程澈(回头):那是您的选择
【云想的自我怀疑】
5-2 场 日 内 学校图书馆
人物:云想、观鹤
△云想独自在图书馆学习,心不在焉
△观鹤坐到她对面
观鹤:想想,你看起来心情不好
云想:观鹤,你说我和程澈真的合适吗?
观鹤:为什么这么问?
云想:我们的出身差距太大了,他的家人肯定不会接受我
观鹤:想想,真正的爱情不应该被出身束缚
云想:可是现实很残酷...
观鹤:如果你真的爱他,就应该相信他的选择
△云想陷入沉思
观鹤:想想,不管你做什么决定,我都会支持你
云想:谢谢你,观鹤
【程澈的坚持】
5-3 场 黄昏 外 学校操场
人物:程澈、云想
△程澈找到云想,发现她在哭
程澈(心疼):怎么了?谁欺负你了?
云想:程澈,我们分手吧
△程澈震惊
程澈:为什么?
云想:我们不合适,你的家人不会接受我的
程澈:我不在乎他们的想法
云想:但是我在乎!我不想成为你的负担
△程澈紧紧抱住云想
程澈:云想,听我说。不管发生什么,我都不会放弃你
云想:可是...
程澈:没有可是。我程澈说过的话,从来不会反悔
△程澈捧起云想的脸
程澈:相信我,好吗?
云想(哭着点头):嗯...
【危机升级 - 绑架事件】
5-4 场 夜 外 回家路上
人物:云想、神秘人、程澈
△云想独自走在回家的路上
△突然被几个黑衣人包围
黑衣人甲:云想小姐,跟我们走一趟
云想(害怕):你们是谁?
黑衣人乙:有人想见你
△云想想要逃跑,被抓住
△正在此时,程澈的摩托车声响起
程澈(冷声):放开她
黑衣人甲:程少爷,我们只是奉命行事
程澈:奉谁的命?
△一辆黑色轿车停下,林董事长走出来
林董事长:是我的命
程澈(愤怒):林叔叔,您这是什么意思?
林董事长:我要让这个女孩知道,她配不上你
△程澈挡在云想面前
程澈:想动她,先过我这关
林董事长:程澈,你要为了一个女孩跟我翻脸?
程澈:如果您要伤害她,那就是
【第5集结尾钩子】
5-5 场 夜 外 回家路上(接上场)
△对峙中,程澈的手机响起
△来电显示:爸爸
程澈(接电话):什么事?
程枭(电话):小澈,立刻回来,出大事了
程澈:什么大事?
程枭:林家撤资了,公司股价暴跌,董事会要求你立刻和林雅订婚
△程澈脸色大变
△林董事长得意地笑了
林董事长:程澈,现在你还要坚持吗?
△云想听到电话内容,眼中闪过痛苦
云想(对程澈):去吧,公司更重要
程澈(坚决):不,你更重要
△程澈挂断电话,牵起云想的手
程澈:我们走
【第5集完】
==== 第6集最终选择爱情胜利 ====
【董事会摊牌】
6-1 场 日 内 程氏集团会议室
人物:程澈、程枭、各位董事、林董事长
△紧急董事会召开
△程澈被要求出席
董事甲:程澈,因为你的任性,公司损失惨重
董事乙:你必须立刻和林雅订婚,挽回林家的合作
程澈:我拒绝
△会议室一片哗然
程枭:小澈,你知道你在说什么吗?
程澈:我很清楚。我不会为了商业利益出卖我的感情
林董事长:程澈,你要为你的选择负责
程澈:我会负责,但不是用这种方式
△程澈站起来,面对所有人
程澈:各位叔叔,我程澈从小就被培养成程氏的继承人。但是今天,我要告诉你们,如果继承程氏意味着要放弃我爱的人,那我宁可不要
△全场震惊
程澈:从今天开始,我放弃程氏集团的继承权
程枭:程澈!
程澈:爸,对不起。但是我不能违背自己的心
【云想的成长 - 主动出击】
6-2 场 日 内 学校教室
人物:云想、林雅、全班同学
△云想主动找到林雅
云想:林雅,我们谈谈
林雅(得意):有什么好谈的?程澈很快就会是我的未婚夫了
云想:我不会让你得逞的
林雅(冷笑):就凭你?
△云想拿出手机,播放一段录音
△录音内容:林雅指使人威胁云想的对话
云想:这段录音如果传出去,你觉得程澈会怎么看你?
林雅(慌张):你...你想干什么?
云想:我要你公开道歉,并且永远不要再骚扰我和程澈
△全班同学围观,议论纷纷
云想(大声):我云想虽然出身贫寒,但我有自己的尊严。我不会因为任何人的威胁而放弃我的爱情
△同学们纷纷鼓掌
学生甲:云想说得对!
学生乙:真正的爱情不应该被门第束缚!
学生丙:我们支持你!
【程澈的惊喜 - 隐藏实力曝光】
6-3 场 日 内 程氏集团会议室
人物:程澈、程枭、董事们、神秘助理
△正当董事会准备通过决议时,程澈的助理进来
助理:程少爷,您要的文件
程澈:谢谢
△程澈拿出一叠文件
程澈:各位,在我放弃继承权之前,我想让你们看看这个
△程澈将文件分发给每个人
△董事们看后纷纷震惊
董事甲:这...这是什么?
程澈:这是我这三年来秘密投资的项目清单
董事乙:天哪,这些项目的总价值...
程澈:超过程氏集团目前的市值
△程枭震惊地看着儿子
程枭:小澈,你什么时候...
程澈:爸,您以为我这三年只是在上学吗?我一直在为接管程氏做准备
△程澈站起来,气场强大
程澈:林家的撤资确实会让程氏损失,但不会伤筋动骨。相反,我的这些项目,足以让程氏的实力翻倍
林董事长(慌张):这不可能...
程澈:林叔叔,您可以选择继续合作,也可以选择离开。但是,请不要再威胁我的女人
【大团圆结局】
6-4 场 黄昏 外 学校天台
人物:程澈、云想
△程澈找到云想,将她拉入怀中
程澈:听说你今天很勇敢
云想:我不想再做被保护的小女孩了
程澈:那你想做什么?
云想:我想做能够站在你身边的女人
△程澈深情地看着云想
程澈:云想,你知道吗?从第一眼看到你,我就知道,你就是我要找的人
云想:为什么?
程澈:因为你让我相信,这个世界上还有纯真的美好
△程澈单膝跪下,拿出一枚戒指
程澈:云想,虽然我们还年轻,但我想让全世界都知道,你是我程澈这辈子唯一的女人。你愿意接受这枚承诺戒指吗?
△云想感动得泪流满面
云想:我愿意
△程澈为云想戴上戒指,两人拥吻
△夕阳西下,两人的身影被拉得很长
【第6集结尾 - 完美收官】
6-5 场 夜 内 程家客厅
人物:程澈、云想、程枭、程澈母亲
△程澈带云想回家见父母
△程枭和程澈母亲已经在客厅等候
程枭:想想,对不起,之前的事情是叔叔不对
云想:程叔叔,您不用道歉
程澈母亲:想想,欢迎你成为我们家的一员
△程澈母亲拿出一条项链
程澈母亲:这是程家传了三代的项链,现在它属于你了
云想(感动):阿姨,这太贵重了...
程澈母亲:你是小澈选择的人,就是我们的女儿
△程澈握住云想的手
程澈:从今以后,没有人能够分开我们
云想:嗯,我们永远在一起
△镜头拉远,一家人其乐融融
△字幕出现:"真正的爱情,能够战胜一切阻碍"
【第6集完】
==== 创作说明 ====
【第4-6集改编亮点】
1. **关系确立**第4集直接确立恋爱关系节奏紧凑
2. **冲突升级**:家族压力、商业威胁、绑架危机层层递进
3. **人物成长**:云想从被动接受保护到主动反击
4. **爽点密集**:程澈护妻、实力曝光、完美反击
5. **情感升华**:从保护关系升华为平等的爱情
【商业化设计】
1. **付费点**:程澈实力曝光、求婚场面、家族认可
2. **话题性**:霸总放弃继承权、灰姑娘逆袭、真爱胜利
3. **情绪调动**:甜虐并存,观众情绪过山车
4. **代入感**:每个女孩都梦想被这样宠爱
【与原著对比】
- 大幅压缩时间线,删除冗余情节
- 强化程澈的霸总属性和保护欲
- 增加商业斗争元素,提升戏剧冲突
- 云想的成长弧线更加明显和励志
- 结局更加圆满,满足观众期待

View File

@ -0,0 +1,445 @@
【第7-9集剧本 - 危机考验,感情波折】
==== 第7集新的威胁信任危机 ====
【神秘敌人出现】
7-1 场 日 外 咖啡厅
人物:云想、神秘男子(陈总)、程澈
△云想独自在咖啡厅等程澈
△一个中年男子坐到她对面
陈总:云想小姐,我们终于见面了
云想(警惕):你是谁?
陈总:我姓陈,是程氏集团的竞争对手
云想:你想干什么?
陈总:我想跟你做个交易
△陈总拿出一张支票
陈总:一千万,离开程澈
云想(愤怒):你以为我是什么人?
陈总:每个人都有价格,只是多少的问题
云想:我不会为了钱背叛程澈
△陈总收起支票,拿出一叠照片
陈总:那这些呢?
△照片内容程澈和其他女孩的亲密照片PS的
陈总:程澈在你之前,可是有很多女朋友的
云想(震惊):这些照片...
陈总:都是真的。你以为你是他的唯一吗?
△正在此时,程澈出现
程澈(冷声):陈总,你在这里做什么?
陈总(起身):程少爷,只是偶遇你的女朋友,聊聊天
程澈:以后不要再接近她
陈总:程少爷,有些事情,瞒得了一时,瞒不了一世
△陈总离开,留下照片
△程澈看到照片,脸色大变
程澈:云想,这些照片...
云想(冷淡):你不用解释
程澈:这些都是假的!
云想:是吗?那为什么你看到照片会这么紧张?
【误会加深】
7-2 场 日 内 学校教室
人物:云想、宋谨、观鹤
△云想心不在焉地上课
△宋谨偷偷递纸条给她
纸条内容:"想想,澈哥找你"
△云想看了一眼,没有理会
△下课后,观鹤走到云想身边
观鹤:想想,你和程澈吵架了?
云想:没有
观鹤:但是你看起来很不开心
云想:观鹤,你觉得一个人会为了另一个人改变吗?
观鹤:如果是真爱的话,会的
云想:那如果这个人以前有很多女朋友呢?
观鹤:过去不重要,重要的是现在
△云想陷入沉思
【程澈的解释】
7-3 场 黄昏 外 学校天台
人物:程澈、云想
△程澈终于找到云想
程澈:云想,我们需要谈谈
云想:没什么好谈的
程澈:关于那些照片,我可以解释
云想:你不用解释,我理解
程澈:你理解什么?
云想:你是程氏集团的少爷,身边有很多女孩很正常
△程澈急了
程澈:云想,你听我说,那些照片都是假的!
云想:假的?那为什么做得这么逼真?
程澈:因为有人想要破坏我们的关系
云想:程澈,你觉得我很好骗吗?
△云想转身要走,程澈拉住她
程澈:云想,相信我,好吗?
云想:程澈,我累了。我们冷静一下吧
△云想挣脱程澈的手,离开
△程澈一个人站在天台上,表情痛苦
【第7集结尾钩子】
7-4 场 夜 内 程澈房间
人物:程澈、宋谨(电话)
△程澈独自坐在房间里,看着云想的照片
△手机响起,是宋谨的电话
宋谨(电话):澈哥,我查到了那些照片的来源
程澈:说
宋谨:是陈氏集团的人做的,他们想要搞垮你
程澈:我知道了
宋谨:澈哥,你打算怎么办?
程澈:我要让他们付出代价
△程澈眼中闪过危险的光芒
程澈:敢动我的女人,他们死定了
【第7集完】
==== 第8集危机升级感情破裂 ====
【陈总的阴谋】
8-1 场 日 内 陈氏集团办公室
人物:陈总、助理、林雅
△陈总在办公室里得意地看着监控画面
△画面中是程澈和云想冷战的场景
陈总:很好,他们开始互相怀疑了
助理:陈总,下一步怎么办?
陈总:继续加码
△林雅走进办公室
林雅:陈叔叔,您找我?
陈总:雅雅,是时候执行第二阶段计划了
林雅:什么计划?
陈总:让程澈彻底失去云想
△陈总拿出一瓶药
陈总:这是迷药,你想办法让云想喝下去
林雅:然后呢?
陈总:然后让程澈看到你们在一起的画面
林雅(犹豫):这样不太好吧...
陈总:你想要程澈,就必须付出代价
【云想中计】
8-2 场 日 内 学校咖啡厅
人物:云想、林雅
△云想独自在咖啡厅喝咖啡
△林雅主动坐到她对面
林雅:想想,我们谈谈吧
云想:我们没什么好谈的
林雅:关于程澈的事情
云想:什么?
林雅:我知道你们吵架了
云想:这不关你的事
林雅:想想,其实我们可以做朋友的
△林雅推了一杯咖啡给云想
林雅:这是我的道歉,之前的事情是我不对
云想(意外):你...
林雅:我想通了,如果程澈真的爱你,我也不应该强求
△云想被感动,喝了咖啡
△几分钟后,云想开始感到头晕
云想:我...我怎么了?
林雅(假装关心):想想,你没事吧?我送你去休息
【程澈误会】
8-3 场 日 内 学校休息室
人物:云想(昏迷)、林雅、程澈
△林雅将昏迷的云想带到休息室
△然后发短信给程澈:"快来休息室,云想出事了"
△程澈匆忙赶到,看到林雅在照顾云想
程澈:她怎么了?
林雅:不知道,突然就晕倒了
程澈(担心):有没有叫医生?
林雅:已经叫了
△程澈想要抱起云想
△云想在迷药作用下,迷迷糊糊地推开程澈
云想(迷糊):不要...不要碰我...
程澈(震惊):云想?
云想(迷糊):我不想看到你...
△程澈心如刀割
△林雅在旁边假装安慰
林雅:程澈,也许她真的需要时间冷静
程澈:不,她不是这样的人
林雅:人在生气的时候,会说很多伤人的话
【真相部分揭露】
8-4 场 日 内 医务室
人物:云想、校医、程澈、宋谨
△云想被送到医务室
△校医检查后,脸色严肃
校医:这个学生被下了迷药
程澈(愤怒):什么?
校医:血液中有迷药成分,幸好剂量不大
宋谨:谁会给想想下药?
△程澈想起林雅的异常表现
程澈:林雅!
△程澈冲出医务室,去找林雅
△但林雅已经离开学校
【云想的决定】
8-5 场 夜 内 云想房间
人物:云想、程澈
△云想醒来后,程澈守在她身边
程澈:你醒了?感觉怎么样?
云想:我...发生了什么?
程澈:你被人下了迷药
云想(震惊):什么?
程澈:是林雅做的
云想:为什么?
程澈:因为有人想要破坏我们的关系
△云想沉默了很久
云想:程澈,我想我们应该分开一段时间
程澈:为什么?现在真相已经清楚了
云想:正是因为真相清楚了,我才更害怕
程澈:害怕什么?
云想:害怕因为我,你会遇到更多的危险
△程澈紧紧抱住云想
程澈:云想,不要离开我
云想(流泪):程澈,我爱你,正是因为爱你,我才不能害你
【第8集结尾钩子】
8-6 场 夜 外 云想家楼下
人物:云想、神秘电话
△云想独自站在楼下
△手机响起,是陌生号码
神秘声音:云想,考虑得怎么样?
云想:你是谁?
神秘声音:一个想要保护程澈的人
云想:什么意思?
神秘声音:只要你离开他,他就会安全
云想:如果我不离开呢?
神秘声音:那他就会有生命危险
△电话挂断,云想脸色苍白
云想OS为了保护程澈我必须离开他
【第8集完】
==== 第9集生死考验真爱觉醒 ====
【云想的牺牲】
9-1 场 晨 内 云想房间
人物:云想
△云想收拾行李,准备离开
△拿起程澈送的戒指,眼中含泪
云想OS程澈对不起。我这样做都是为了保护你
△云想写了一封信,放在桌上
△信的内容:"程澈,我们不合适,请忘记我。- 云想"
【程澈的发现】
9-2 场 日 内 程澈房间
人物:程澈、宋谨
△程澈发现云想不见了
△冲到她的房间,看到信件
程澈(愤怒):不可能!她不会这样做!
宋谨:澈哥,也许她真的...
程澈:不!一定有人威胁了她!
△程澈拿出手机,疯狂拨打云想的号码
△但云想的手机已经关机
程澈:宋谨,动用所有关系,一定要找到她!
宋谨:是,澈哥!
【陈总的最后一击】
9-3 场 日 内 废弃仓库
人物:云想、陈总、手下
△云想被带到一个废弃仓库
△陈总出现在她面前
陈总:云想小姐,欢迎来到我的地盘
云想:你想要什么?
陈总:很简单,给程澈打个电话,告诉他你不爱他了
云想:我不会的
陈总:那就别怪我不客气了
△陈总的手下逼近云想
△云想害怕地后退
陈总:程澈为了你,已经得罪了很多人。现在,是时候让他付出代价了
云想:你们想对程澈做什么?
陈总:如果你不配合,他就会出车祸
△陈总拿出手机,播放程澈开车的实时画面
陈总:我的人已经在路上等他了
云想(恐惧):不要伤害他!
陈总:那就配合我
【程澈的营救】
9-4 场 日 外 废弃仓库外
人物:程澈、宋谨、保镖
△程澈通过GPS定位找到了云想
△带着保镖包围了仓库
程澈(对讲机):所有人注意,确保云想的安全
宋谨:澈哥,陈总的人很多
程澈:我不在乎。今天,我一定要救出云想
△程澈冲进仓库
【最终对决】
9-5 场 日 内 废弃仓库
人物:程澈、云想、陈总、双方手下
△程澈出现在仓库里
程澈:放开她!
陈总:程澈,你终于来了
程澈:你想要什么?
陈总:我要你跪下,求我放过她
△程澈毫不犹豫地跪下
程澈:我求你,放过她
云想(震惊):程澈,不要!
陈总(得意):堂堂程氏集团的少爷,居然为了一个女人下跪
程澈:只要你放过她,我什么都愿意做
△云想被感动得泪流满面
云想:程澈,你为什么要这样做?
程澈:因为我爱你,胜过我的生命
△正在此时,警察包围了仓库
△原来程澈早就报了警
陈总(慌张):不可能!
程澈(站起来):陈总,游戏结束了
【真爱告白】
9-6 场 黄昏 外 医院
人物:程澈、云想
△云想在医院接受检查
△程澈守在她身边
云想:程澈,对不起,我不应该不相信你
程澈:是我不好,没有保护好你
云想:程澈,你为什么愿意为我做这么多?
程澈:因为你是我的全世界
△程澈握住云想的手
程澈:云想,经过这次的事情,我更加确定,我这辈子只爱你一个人
云想:我也是,程澈。我永远不会再离开你
△两人深情拥吻
【第9集结尾钩子】
9-7 场 夜 内 程澈房间
人物:程澈、云想
△两人相拥而眠
△程澈的手机响起,是一条短信
△短信内容:"程澈,这只是开始。- 神秘人"
△程澈看到短信,眉头紧皱
△但他没有吵醒云想,而是将她抱得更紧
程澈OS不管还有什么威胁我都会保护好云想
【第9集完】
==== 创作说明 ====
【第7-9集改编亮点】
1. **危机升级**:从情感误会到生命威胁,层层递进
2. **人物考验**:通过危机考验两人的真爱
3. **反派立体化**:陈总和林雅的阴谋更加复杂
4. **情感深化**:通过分离和重聚,感情更加深厚
5. **动作戏份**:增加营救戏码,提升观赏性
【情绪设计】
1. **虐心情节**:误会、分离、威胁制造情绪波动
2. **甜蜜反转**:危机后的重聚更加珍贵
3. **英雄救美**:程澈为爱下跪,展现真爱力量
4. **成长弧线**:云想学会为爱勇敢,程澈学会为爱牺牲
【商业价值】
1. **话题性**:霸总为爱下跪、生死营救等话题
2. **情绪商品**:虐恋情深,观众情绪投入度高
3. **付费点**:营救高潮、真爱告白等关键情节
4. **完播率**:每集结尾的悬念设置
【与原著对比】
- 大幅增加动作戏和悬疑元素
- 强化反派威胁,提升戏剧张力
- 压缩时间线,删除冗余支线
- 情感线更加极致化和戏剧化

View File

@ -0,0 +1,75 @@
【诊断与资产评估报告】
==== 故事内核诊断 ====
核心故事线:校园青春恋爱 + 成长治愈
- 失去父亲的孤独少女云想 VS 外冷内热的学霸程澈
- 从互相看不顺眼到暗生情愫的经典"欢喜冤家"模式
- 治愈系成长:程澈的出现如"一束光"照亮云想的黑暗世界
情感内核强度:★★★☆☆
- 有一定的情感基础,但缺乏足够的戏剧张力
- 节奏偏慢,爽点密度不足
==== 可继承的宝贵资产 ====
【高光情节】
1. 程澈为云想打架护短第6-7集- 经典"护妻打脸"素材
2. 咖啡店"上帝"调戏桥段第20集- 甜宠互动,网感十足
3. 音乐会深情献唱第25集- 公开示爱,情感高潮
4. 程澈霸道赶走搭讪男第21集- 占有欲爆棚,观众爽点
【神来之笔对白】
- "她是我的人,想欺负她,先看看自己几斤几两!"
- "你是不是舍不得我?" "没有。" "真的?"
- "上帝,对不起,请原谅我!"(当众羞辱反转)
【独特人设闪光点】
- 程澈:外冷内热学霸 + 隐藏宠妻属性 + 毒舌傲娇
- 云想:治愈系少女 + 天然呆萌 + 坚强独立
==== 核心问题诊断 ====
【致命伤】
1. 节奏拖沓27集才到暧昧期短剧黄金法则是3集定生死
2. 爽点稀薄:缺乏密集的"打脸""逆袭""宠溺"等核心爽点
3. 冲突不够:程澈家庭接纳云想过于顺利,缺乏戏剧张力
4. 人设模糊:两人都太"正常",缺乏极致化标签
【次要问题】
1. 配角功能性不强:宋谨、观鹤等缺乏明确的推动剧情作用
2. 情感递进过于平缓:缺乏情绪过山车体验
3. 网络梗语不足:对话偏文艺,缺乏当下网感
==== 短剧改编潜力评估 ====
商业价值:★★★★☆
- 校园恋爱+治愈系是短剧热门赛道
- 男女主人设有改造空间,可塑性强
- 核心情感线清晰,适合短剧快节奏
改编难度:★★★☆☆
- 需要大幅压缩节奏,前置爽点
- 人设需要极致化改造
- 冲突线需要重新设计
==== 初步改编建议 ====
【核心策略】
将温吞校园恋爱魔改为"战神学霸归来,护妻打脸"的极致爽文模式
【关键改造点】
1. 人设极致化:程澈→隐藏身份的天才学霸+宠妻狂魔;云想→被欺凌的灰姑娘+逆袭女王
2. 冲突前置:开篇即安排云想被校园霸凌,程澈强势护短
3. 爽点密集化每集至少2个打脸/宠溺/逆袭爽点
4. 节奏压缩27集压缩至12-15集3集内确立CP关系
【预期效果】
完播率提升40%付费转化率提升60%
==== 结论 ====
这是一个具有良好改编基础的校园恋爱故事,核心情感线和人物关系清晰,但需要进行"爽文化"改造以适应短剧市场。通过节奏压缩、人设极致化、冲突强化等手段,有望打造成爆款短剧。
改编信心指数85%
预期市场表现A级头部20%

View File

@ -0,0 +1,235 @@
【重大事件时间线.txt - 剧本圣经】
==== 时间线总览 ====
【故事时间跨度】高三下学期约4个月
【叙事节奏】:快节奏,密集事件推进
【关键时间节点】12个重大事件对应12集内容
==== 详细时间线 ====
【第1周 - 命运相遇】
**Day 1 - 第1集霸气出场**
- 上午:云想被校园恶霸在食堂羞辱
- 中午:程澈霸气出场,一打三护短
- 下午:程澈接到神秘电话,身份暗示
- 晚上:程澈对云想说"以后跟着我"
关键转折点:两人命运交汇,保护关系建立
情感温度从0°升至30°
**Day 2-3 - 第2集宠妻日常**
- Day 2上午程澈为云想准备爱心早餐
- Day 2下午程澈为云想出头对抗老师
- Day 2晚上程澈送云想回家
- Day 3观鹤温柔出场成为潜在情敌
关键转折点:宠妻模式开启,情敌出现
情感温度从30°升至50°
**Day 4-5 - 第3集吃醋宣示**
- Day 4观鹤邀请云想参加音乐社
- Day 4下午程澈吃醋霸道阻止
- Day 4晚上程澈当众宣示主权
- Day 5程澈展现天才实力神秘人调查
关键转折点:占有欲爆发,身份线推进
情感温度从50°升至70°
---
【第2周 - 身份震撼】
**Day 6-7 - 第4集天才曝光**
- Day 6程澈国际奥数冠军身份曝光
- Day 6下午全校震惊云想自卑
- Day 7云想开始逃避程澈
- Day 7晚上程澈开启追妻模式
关键转折点:身份差距显现,感情危机
情感温度从70°降至40°
**Day 8-10 - 第5集确立关系**
- Day 8云想主动为程澈准备惊喜
- Day 9两人正式确立恋爱关系
- Day 10甜蜜日常程澈为云想庆生
- Day 10晚上林雅未婚妻出现预告
关键转折点:正式成为情侣,新威胁来临
情感温度从40°飙升至90°
---
【第3周 - 情敌考验】
**Day 11-12 - 第6集情敌来袭**
- Day 11林雅强势登场威胁云想
- Day 11下午云想受打击选择离开
- Day 12程澈愤怒反击拒绝未婚妻
- Day 12晚上程澈坚定选择云想
关键转折点:面临情敌威胁,程澈做出选择
情感温度从90°降至60°再升至85°
**Day 13-14 - 第7集家族压力**
- Day 13程澈父亲施压要求分手
- Day 13下午程澈拒绝宁可断绝关系
- Day 14云想觉醒决定为爱而战
- Day 14晚上两人更加珍惜彼此
关键转折点:家族对抗,云想成长觉醒
情感温度从85°降至50°再升至80°
---
【第4周 - 华丽逆袭】
**Day 15-16 - 第8集天赋觉醒**
- Day 15学校音乐比赛报名
- Day 16云想音乐天赋爆发一鸣惊人
- Day 16下午全校刮目相看
- Day 16晚上程澈为云想骄傲庆祝
关键转折点:云想华丽逆袭,证明自己
情感温度从80°升至95°
---
【第6周 - 生死考验】
**Day 17-18 - 第9集最大危机**
- Day 17程澈完整身份曝光企业继承人+天才黑客)
- Day 17下午商业对手绑架云想
- Day 18程澈动用所有资源营救
- Day 18晚上成功救出云想消除威胁
关键转折点:生死考验,感情升华
情感温度从95°降至20°再飙升至100°
---
【第8周 - 公开宣示】
**Day 19-20 - 第10集公开关系**
- Day 19学校大会程澈公开表白
- Day 19下午程澈父母正式接纳云想
- Day 20云想完美蜕变成为风云人物
- Day 20晚上两人开始规划未来
关键转折点:公开关系,获得认可
情感温度稳定在100°
---
【第10-12周 - 甜蜜日常】
**Day 21-25 - 第11集幸福满溢**
- Day 21-23校园甜蜜日常撒糖不断
- Day 24两人规划大学和未来
- Day 25解决所有遗留问题达成和解
关键转折点:进入稳定期,准备结局
情感温度持续100°
---
【第16周 - 完美结局】
**毕业典礼日 - 第12集永远幸福**
- 上午:毕业典礼,双双获得荣誉
- 中午:程澈在典礼上浪漫求婚
- 下午:云想含泪答应,全场祝福
- 未来:携手走向美好人生
关键转折点:完美结局,永远幸福
情感温度达到巅峰120°
==== 关键节点分析 ====
【情感升温节点】
1. Day 1初次相遇保护关系建立0°→30°
2. Day 2-3宠妻日常开启30°→50°
3. Day 4-5占有欲爆发50°→70°
4. Day 9确立恋爱关系40°→90°
5. Day 16云想逆袭成功80°→95°
6. Day 18生死考验后20°→100°
【情感危机节点】
1. Day 6身份差距显现70°→40°
2. Day 11情敌威胁90°→60°
3. Day 13家族压力85°→50°
4. Day 17生死危机95°→20°
【重大转折节点】
1. Day 1命运相遇
2. Day 6身份曝光
3. Day 9确立关系
4. Day 11情敌出现
5. Day 16华丽逆袭
6. Day 17生死考验
7. Day 19公开宣示
8. 毕业日:完美结局
==== 节奏控制策略 ====
【快节奏推进原则】
- 每2-3天一个重大事件
- 情感温度大起大落,制造过山车体验
- 危机与甜蜜交替出现,保持观众情绪在线
【爽点分布密度】
- 护短打脸Day 1, 4, 11, 17
- 宠妻甜蜜Day 2, 9, 16, 21-25
- 身份震撼Day 1, 6, 17
- 逆袭反击Day 6, 16, 19
- 占有宣示Day 4, 12, 19
【钩子设置时机】
每个重大事件结束时都设置强钩子:
- Day 1结尾"以后跟着我,没人敢欺负你"
- Day 3结尾神秘人要揭露程澈身份
- Day 5结尾程澈身份即将曝光
- Day 7结尾云想决定努力变优秀
- Day 10结尾程澈未婚妻出现
- Day 12结尾家族要断绝父子关系
- Day 14结尾云想隐藏天赋被发现
- Day 16结尾更大危机即将来临
- Day 18结尾两人感情更加坚定
- Day 20结尾开始规划美好未来
- Day 25结尾毕业典礼即将到来
==== 商业化时间节点 ====
【付费转化关键时刻】
1. Day 4晚上程澈吃醋大戏第3集结尾
2. Day 11下午情敌对决高潮第6集结尾
3. Day 17晚上生死营救第9集结尾
4. 毕业典礼浪漫求婚第12集结尾
【完播率保障节点】
每集结尾的强钩子确保观众必须看下一集
==== 原著对比时间线 ====
【原著27集 vs 改编12集】
- 原著1-9集内容 → 改编第1-2集大幅压缩日常突出冲突
- 原著10-18集内容 → 改编第3-6集强化情敌线增加家族压力
- 原著19-27集内容 → 改编第7-12集新增生死考验强化逆袭
【关键改动】
1. 删除大量日常铺垫,直接进入冲突
2. 前置音乐会情节,作为逆袭高光时刻
3. 新增绑架营救情节,增强戏剧张力
4. 压缩感情发展时间,快速确立关系
5. 强化反派戏份,增加打脸爽点
==== 执行要点 ====
1. **严格按时间线执行**:确保每个关键节点按时到达
2. **情感温度监控**:实时监控观众情绪,适时调整
3. **钩子强度检验**:每个钩子都要能让观众"停不下来"
4. **节奏感把控**:快慢结合,张弛有度
5. **商业节点重点**:付费转化时刻要重点打磨
这份时间线将确保我们的改编节奏紧凑,情节密集,每个关键节点都能最大化观众的情绪体验和商业价值。

0
graph/__init__.py Normal file
View File

292
graph/test_agent_graph_1.py Normal file
View File

@ -0,0 +1,292 @@
"""智能编剧系统工作流图定义
该模块定义了智能编剧系统的完整工作流程图包括各个节点和边的连接关系
"""
from typing import TypedDict, Annotated, Dict, Any, List, TypedDict, Optional
from agent.scheduler import SchedulerAgent
from agent.build_bible import BuildBibleAgent
from agent.episode_create import EpisodeCreateAgent
from agent.script_analysis import ScriptAnalysisAgent
from agent.strategic_planning import StrategicPlanningAgent
from langgraph.graph import StateGraph, START, END
from utils.logger import get_logger
import operator
logger = get_logger(__name__)
# 定义一个简单的替换函数
def replace_value(old_val, new_val):
"""一个简单的合并函数,用于替换旧值"""
return new_val
# 状态类型定义
class InputState(TypedDict):
"""工作流输入状态"""
input_data: Annotated[Dict[str, Any], operator.add]
session_id: Annotated[str, replace_value]
class OutputState(TypedDict):
"""工作流输出状态"""
session_id: Annotated[str, replace_value]
status: Annotated[str, replace_value]
error: Annotated[str, replace_value]
class NodeInfo(TypedDict):
"""工作流信息"""
step: Annotated[str, replace_value] # 阶段名称 [wait_for_input,script_analysis,strategic_planning,build_bible,episode_create_loop, finish]
status: Annotated[str, replace_value] # 当前阶段的状态 [waiting,running,failed,completed]
reason: Annotated[str, replace_value] # 失败原因
retry_count: Annotated[int, replace_value] # 重试次数
from_type: Annotated[str, replace_value] # 本次请求来着哪里 [user, agent]
class ScriptwriterState(TypedDict, total=False):
"""智能编剧工作流整体状态"""
# 输入数据
input_data: Annotated[Dict[str, Any], operator.add]
session_id: Annotated[str, replace_value]
# 节点间状态
node_info: NodeInfo
# 中间状态
agent_script_id: Annotated[str, replace_value] # 剧本ID 包括原文
agent_plan: Annotated[Dict[str, Any], replace_value] #剧本计划
script_bible: Annotated[Dict[str, Any], replace_value] #剧本圣经
episode_list: Annotated[List, replace_value] # 章节列表 完成状态、产出章节id
# 输出数据
status: Annotated[str, replace_value]
error: Annotated[str, replace_value]
class ScriptwriterGraph:
"""智能编剧工作流图类
管理智能编剧系统的完整工作流程包括
- 剧本接收
- 诊断分析
- 策略制定
- 剧本圣经构建
- 剧本创作
- 迭代调整
"""
def __init__(self):
"""初始化工作流图"""
self.graph = None
self._build_graph()
def node_router(self, state: ScriptwriterState) -> str:
next_node = state.get("node", '')
if next_node:
return next_node
else:
return END
def _build_graph(self) -> None:
"""构建工作流图"""
try:
# 创建智能体
# 调度智能体
schedulerAgent = SchedulerAgent(
tools=[],
SchedulerList=[
{
"scheduler_node": "调度智能体节点",
"script_analysis_node": "原始剧本分析节点",
"strategic_planning_node": "确立改编目标节点",
"build_bible_node": "剧本圣经构建节点",
"episode_create_node": "单集创作节点",
"end_node": "结束节点,任务失败终止时使用,结束后整个工作流将停止"
}
]
)
scriptAnalysisAgent = ScriptAnalysisAgent(
tools=[],
SchedulerList=[
{
"scheduler_node": "调度智能体节点",
}
]
)
strategicPlanningAgent = StrategicPlanningAgent(
tools=[],
SchedulerList=[
{
"scheduler_node": "调度智能体节点",
}
]
)
buildBibleAgent = BuildBibleAgent(
tools=[],
SchedulerList=[
{
"scheduler_node": "调度智能体节点",
}
]
)
episodeCreate = EpisodeCreateAgent(
tools=[],
SchedulerList=[
{
"scheduler_node": "调度智能体节点",
}
]
)
# 创建状态图
workflow = StateGraph(ScriptwriterState, input_schema=InputState, output_schema=OutputState)
# 添加节点
workflow.add_node("scheduler_node", self.scheduler_node)
workflow.add_node("script_analysis_node", self.script_analysis_node)
workflow.add_node("strategic_planning_node", self.strategic_planning_node)
workflow.add_node("build_bible_node", self.build_bible_node)
workflow.add_node("episode_create_node", self.episode_create_node)
workflow.add_node("end_node", self.end_node)
# 添加边
workflow.set_entry_point("scheduler_node")
# 所有功能节点执行完成后,都返回给调度节点
workflow.add_edge("script_analysis_node", "scheduler_node")
workflow.add_edge("strategic_planning_node", "scheduler_node")
workflow.add_edge("build_bible_node", "scheduler_node")
workflow.add_edge("episode_create_node", "scheduler_node")
# 添加条件边:由调度节点决定下一个路由
workflow.add_conditional_edges(
"scheduler_node",
self.node_router,
{
"script_analysis_node": "script_analysis_node",
"strategic_planning_node": "strategic_planning_node",
"build_bible_node": "build_bible_node",
"episode_create_node": "episode_create_node",
# 用户确认和暂停逻辑在这里处理,不需要单独的边
"end_node": "end_node",
}
)
workflow.add_edge("end_node", END)
# 编译图
self.graph = workflow.compile()
logger.info("工作流图构建完成")
except Exception as e:
logger.error(f"构建工作流图失败: {e}")
raise
# --- 定义图中的节点 ---
async def scheduler_node(self, state: ScriptwriterState)-> ScriptwriterState:
"""第一步:初步沟通,请求剧本"""
session_id = state.get("session_id", "")
return {}
async def script_analysis_node(self, state: ScriptwriterState)-> ScriptwriterState:
"""第二步:诊断分析与资产评估"""
print("\n--- 正在进行诊断分析 ---")
session_id = state.get("session_id", "")
print(f"报告已生成: TEST")
return {}
async def confirm_analysis_node(self, state: ScriptwriterState)-> ScriptwriterState:
"""用户确认分析报告节点"""
print("\n等待用户确认分析报告...")
return {}
async def strategic_planning_node(self, state: ScriptwriterState)-> ScriptwriterState:
"""第三步:确立改编目标与战略蓝图"""
print("\n--- 正在制定战略蓝图 ---")
print(f"战略蓝图已生成: TEST")
return {}
async def build_bible_node(self, state: ScriptwriterState)-> ScriptwriterState:
"""第四步:确立改编目标与战略蓝图"""
print("\n--- 正在制定战略蓝图 ---")
print(f"战略蓝图已生成: TEST")
return {}
async def episode_create_node(self, state: ScriptwriterState)-> ScriptwriterState:
"""第五步:动态创作与闭环校验(循环主体)"""
num_episodes = 3 # 假设每次创作3集
episode_list = []
return {"episode_list": episode_list}
async def end_node(self, state: ScriptwriterState)-> OutputState:
""" 结束节点 处理并完成所有数据状态 """
print(f"langgraph 所有任务完成")
return {
"session_id": state.get("session_id", ""),
"status": "",
"error": "",
}
async def run(self, input_data: Dict[str, Any]) -> OutputState:
"""运行工作流
Args:
input_data: 输入数据
Returns:
工作流执行结果
"""
try:
logger.info("开始运行智能编剧工作流")
# # 初始化状态
# initial_state: InputState = {
# 'input_data': input_data,
# 'session_id': input_data.get('session_id', ''),
# 'max_iterations': input_data.get('max_iterations', 3),
# 'batch_info': input_data.get('batch_info', {})
# }
# # 运行工作流
# if self.graph is None:
# raise RuntimeError("工作流图未正确初始化")
# result = await self.graph.ainvoke(initial_state)
# logger.info(f"工作流执行结果: {result}")
# if not result:
# raise ValueError("工作流执行结果为空")
# # 保存到记忆
# self.memory.save_workflow_result(result)
# # 构造输出状态
# output_result: OutputState = {
# 'script': result.get('script'),
# 'adjustment': result.get('adjustment'),
# 'error': result.get('error'),
# 'iteration_count': result.get('iteration_count', 0)
# }
output_result:OutputState = {
'session_id': "",
'status': 'completed',
'error': '',
}
logger.info("智能编剧工作流运行完成")
return output_result
except Exception as e:
logger.error(f"运行工作流失败: {e}")
raise
def get_graph_visualization(self) -> str:
"""获取工作流图的可视化表示
Returns:
图的文本表示
"""
try:
if self.graph:
return str(self.graph)
return "工作流图未初始化"
except Exception as e:
logger.error(f"获取图可视化失败: {e}")
return f"获取图可视化失败: {e}"

171
graph/test_graph_3.py Normal file
View File

@ -0,0 +1,171 @@
# test_graph_persistent.py
from operator import add
from typing import TypedDict, Annotated
from langchain_core.messages import AnyMessage, HumanMessage
from langgraph import graph
from langgraph.config import get_stream_writer
from langgraph.constants import END, START
from langgraph.graph import StateGraph
from IPython.display import Image
import uuid
import config
# 导入数据库连接和自定义检查点存储器
from tools.database.mongo import mainDB, client
# from mongodb_checkpointer import MongoDBCheckpointSaver
from langgraph.checkpoint.mongodb import MongoDBSaver
import asyncio
# collection = db.langgraph_checkpoints
memory: MongoDBSaver = MongoDBSaver(client, db_name=config.MONGO_CHECKPOINT_DB_NAME)
class State(TypedDict):
messages: Annotated[list[AnyMessage], add]
type: str
class InputState(TypedDict):
user_input: str
class OutputState(TypedDict):
graph_output: str
class OverallState(TypedDict):
foo: str
user_input: str
graph_output: str
class PrivateState(TypedDict):
bar: str
async def node_1(state: InputState) -> OverallState:
print(f"Node 1 处理: {state['user_input']}")
return {"foo": state["user_input"] + ">学院"}
async def node_2(state: OverallState) -> PrivateState:
print(f"Node 2 处理: {state['foo']}")
return {"bar": state["foo"] + ">非常"}
async def node_3(state: PrivateState) -> OverallState:
print(f"Node 3 处理: {state['bar']}")
return {"graph_output": state["bar"] + ">靠谱"}
# 创建 MongoDB 检查点存储器
# checkpointer = MongoDBCheckpointSaver(db.langgraph_checkpoints)
# 构建图,并添加检查点存储器
builder = StateGraph(OverallState, input_schema=InputState, output_schema=OutputState)
builder.add_node('node_1', node_1)
builder.add_node('node_2', node_2)
builder.add_node('node_3', node_3)
builder.add_edge(START, 'node_1')
builder.add_edge('node_1', 'node_2')
builder.add_edge('node_2', 'node_3')
builder.add_edge('node_3', END)
# 编译图并添加检查点存储器
graph = builder.compile(checkpointer=memory)
async def run_with_persistence(user_input: str, thread_id: str = None):
"""运行带持久化的图"""
if thread_id is None:
thread_id = str(uuid.uuid4())
print(f"使用线程 ID: {thread_id}")
# 配置包含线程 ID
config = {"configurable": {"thread_id": thread_id}}
# 执行图
input_state = {"user_input": user_input}
output_state = await graph.ainvoke(input_state, config)
print(f"输出: {output_state}")
return output_state, thread_id
async def get_checkpoint_history(thread_id: str):
"""获取检查点历史"""
config = {"configurable": {"thread_id": thread_id}}
try:
history_generator = memory.list(config, limit=10)
print("正在获取检查点历史...")
# 使用列表推导式或 for 循环来收集所有检查点
history = list(history_generator)
print(f"找到 {len(history)} 个检查点:")
for i, checkpoint_tuple in enumerate(history):
# checkpoint_tuple 包含 config, checkpoint, metadata 等属性
# print(f" - ID: {checkpoint_tuple}")
checkpoint_data = checkpoint_tuple.checkpoint
metadata = checkpoint_tuple.metadata
print(f"检查点 {i+1}:")
print(f" - ID: {checkpoint_data.get('id', 'N/A')}")
print(f" - 状态: {checkpoint_data.get('channel_values', {})}")
print(f" - 元数据: {metadata}")
print("-" * 50)
except Exception as e:
print(f"获取历史记录时出错: {e}")
def resume_from_checkpoint(thread_id: str, checkpoint_id: str = None):
"""从检查点恢复执行"""
config = {"configurable": {"thread_id": thread_id}}
if checkpoint_id:
config["configurable"]["checkpoint_id"] = checkpoint_id
try:
# 获取 CheckpointTuple 对象
checkpoint_tuple = memory.get_tuple(config)
if checkpoint_tuple:
# 直接通过属性访问,而不是解包
checkpoint_data = checkpoint_tuple.checkpoint
metadata = checkpoint_tuple.metadata
print(f"从检查点恢复:")
print(f" - 检查点 ID: {checkpoint_data.get('id', 'N/A')}")
print(f" - 状态: {checkpoint_data.get('channel_values', {})}")
print(f" - 元数据: {metadata}")
return checkpoint_data.get('channel_values', {})
else:
print(f"未找到线程 {thread_id} 的检查点")
return None
except Exception as e:
print(f"恢复检查点时出错: {e}")
return None
if __name__ == "__main__":
print("=== 测试持久化 LangGraph ===")
# 第一次运行
print("\n1. 第一次运行:")
# 由于在异步函数外使用await需要使用asyncio运行
output1, thread_id = asyncio.run(run_with_persistence("你好"))
# 查看检查点历史
print("\n2. 查看检查点历史:")
asyncio.run(get_checkpoint_history(thread_id))
# 从同一线程继续运行
print("\n3. 从同一线程继续运行:")
output2, _ = asyncio.run(run_with_persistence("再见", thread_id))
# 查看更新后的历史
print("\n4. 查看更新后的历史:")
asyncio.run(get_checkpoint_history(thread_id))
# 恢复检查点状态
print("\n5. 恢复最新检查点状态:")
restored_state = resume_from_checkpoint(thread_id)
# 可视化图结构(可选)
# try:
# with open('persistent_graph_visualization.png', 'wb') as f:
# f.write(graph.get_graph().draw_mermaid_png())
# print("\n图片已保存为 persistent_graph_visualization.png")
# except Exception as e:
# print(f"保存可视化图片失败: {e}")

4
handlers/__init__.py Normal file
View File

@ -0,0 +1,4 @@
# handlers/__init__.py
"""
处理器模块初始化文件
"""

View File

@ -0,0 +1,84 @@
from flask import request, jsonify
import asyncio
import uuid
from graph.test_graph_3 import run_with_persistence, get_checkpoint_history, resume_from_checkpoint
def run_async(coro):
"""运行异步函数的辅助函数"""
try:
# 尝试使用现有的事件循环
loop = asyncio.get_running_loop()
except RuntimeError:
# 如果没有运行中的事件循环,则创建一个新的
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
return loop.run_until_complete(coro)
def run_langgraph():
"""启动一个新的langgraph任务"""
try:
data = request.get_json()
user_input = data.get('user_input', '')
thread_id = data.get('thread_id', str(uuid.uuid4()))
if not user_input:
return jsonify({'error': 'user_input is required'}), 400
# 运行异步函数
output, thread_id = run_async(run_with_persistence(user_input, thread_id))
return jsonify({
'status': 'success',
'thread_id': thread_id,
'output': output
})
except Exception as e:
return jsonify({'error': str(e)}), 500
def get_task_status(thread_id):
"""查询任务状态和历史"""
try:
# 获取检查点历史
# 注意这里需要修改get_checkpoint_history以返回数据而不是打印
# history = run_async(get_checkpoint_history(thread_id))
return jsonify({
'status': 'success',
'thread_id': thread_id,
'message': 'Task status endpoint'
})
except Exception as e:
return jsonify({'error': str(e)}), 500
def resume_task(thread_id):
"""从检查点恢复任务"""
try:
data = request.get_json()
checkpoint_id = data.get('checkpoint_id')
# 恢复检查点状态
restored_state = resume_from_checkpoint(thread_id, checkpoint_id)
if restored_state:
return jsonify({
'status': 'success',
'restored_state': restored_state
})
else:
return jsonify({'error': 'Failed to restore checkpoint'}), 404
except Exception as e:
return jsonify({'error': str(e)}), 500
def visualize_graph(thread_id):
"""可视化图结构"""
try:
# 这里可以返回图的可视化信息
# 为了简化,我们只返回基本信息
return jsonify({
'status': 'success',
'thread_id': thread_id,
'message': 'Graph visualization endpoint'
})
except Exception as e:
return jsonify({'error': str(e)}), 500

0
models/__init__.py Normal file
View File

397
models/script_model.py Normal file
View File

@ -0,0 +1,397 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
会话数据模型
定义会话的数据结构和验证逻辑
"""
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, field
from enum import Enum
class SessionStatus(Enum):
"""会话状态枚举"""
QUEUED = "queued" # 排队中
PENDING = "pending" # 等待中
ACTIVE = "active" # 活跃状态
PAUSED = "paused" # 暂停状态
COMPLETED = "completed" # 已完成
CANCELLED = "cancelled" # 已取消
ERROR = "error" # 错误状态
class SessionType(Enum):
"""会话类型枚举"""
SCRIPTWRITING = "scriptwriting" # 编剧创作
CONSULTATION = "consultation" # 咨询对话
REVIEW = "review" # 剧本评审
COLLABORATION = "collaboration" # 协作创作
@dataclass
class SessionModel:
"""
会话数据模型
定义会话的完整数据结构
"""
# 基础信息
user_id: str
session_type: str = SessionType.SCRIPTWRITING.value
title: str = ""
description: str = ""
# 原始剧本内容
original_script: str = ""
# 状态信息
status: str = SessionStatus.ACTIVE.value
current_step: int = 1
total_steps: int = 6
# 配置信息
settings: Dict[str, Any] = field(default_factory=dict)
metadata: Dict[str, Any] = field(default_factory=dict)
# 时间信息
created_at: datetime = field(default_factory=datetime.now)
updated_at: datetime = field(default_factory=datetime.now)
expires_at: datetime = field(default_factory=lambda: datetime.now() + timedelta(days=7))
# 可选字段
session_id: Optional[str] = None
def __post_init__(self):
"""初始化后处理"""
# 验证数据
self.validate()
# 设置默认值
if not self.title:
self.title = f"编剧会话 - {self.created_at.strftime('%Y-%m-%d %H:%M')}"
# 确保设置字典存在必要的键
default_settings = {
'auto_save': True,
'step_timeout': 1800, # 30分钟
'max_retries': 3,
'language': 'zh-CN',
'genre': 'drama',
'style': 'modern'
}
for key, value in default_settings.items():
if key not in self.settings:
self.settings[key] = value
# 确保元数据字典存在
if 'tags' not in self.metadata:
self.metadata['tags'] = []
if 'source' not in self.metadata:
self.metadata['source'] = 'web_interface'
def validate(self) -> bool:
"""
验证数据有效性
Returns:
bool: 是否有效
Raises:
ValueError: 数据无效时抛出异常
"""
# 验证用户ID
if not self.user_id or not isinstance(self.user_id, str):
raise ValueError("用户ID不能为空且必须是字符串")
# 验证会话类型
valid_types = [t.value for t in SessionType]
if self.session_type not in valid_types:
raise ValueError(f"无效的会话类型: {self.session_type},有效值: {valid_types}")
# 验证状态
valid_statuses = [s.value for s in SessionStatus]
if self.status not in valid_statuses:
raise ValueError(f"无效的会话状态: {self.status},有效值: {valid_statuses}")
# 验证步骤
if not isinstance(self.current_step, int) or self.current_step < 1:
raise ValueError("当前步骤必须是大于0的整数")
if not isinstance(self.total_steps, int) or self.total_steps < 1:
raise ValueError("总步骤数必须是大于0的整数")
if self.current_step > self.total_steps:
raise ValueError("当前步骤不能超过总步骤数")
# 验证时间
if self.updated_at < self.created_at:
raise ValueError("更新时间不能早于创建时间")
if self.expires_at <= self.created_at:
raise ValueError("过期时间必须晚于创建时间")
return True
def to_dict(self) -> Dict[str, Any]:
"""
转换为字典格式
Returns:
Dict: 字典数据
"""
data = {
'user_id': self.user_id,
'session_type': self.session_type,
'title': self.title,
'description': self.description,
'original_script': self.original_script,
'status': self.status,
'current_step': self.current_step,
'total_steps': self.total_steps,
'settings': self.settings.copy(),
'metadata': self.metadata.copy(),
'created_at': self.created_at,
'updated_at': self.updated_at,
'expires_at': self.expires_at
}
if self.session_id:
data['session_id'] = self.session_id
return data
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> 'SessionModel':
"""
从字典创建模型实例
Args:
data: 字典数据
Returns:
SessionModel: 模型实例
"""
# 提取必需字段
user_id = data.get('user_id')
if not user_id:
raise ValueError("缺少必需字段: user_id")
# 创建实例
instance = cls(
user_id=user_id,
session_type=data.get('session_type', SessionType.SCRIPTWRITING.value),
title=data.get('title', ''),
description=data.get('description', ''),
status=data.get('status', SessionStatus.ACTIVE.value),
current_step=data.get('current_step', 1),
total_steps=data.get('total_steps', 6),
settings=data.get('settings', {}),
metadata=data.get('metadata', {})
)
# 设置时间字段
if 'created_at' in data:
instance.created_at = data['created_at']
if 'updated_at' in data:
instance.updated_at = data['updated_at']
if 'expires_at' in data:
instance.expires_at = data['expires_at']
# 设置可选字段
if 'session_id' in data:
instance.session_id = data['session_id']
return instance
def update_status(self, new_status: str) -> None:
"""
更新会话状态
Args:
new_status: 新状态
"""
valid_statuses = [s.value for s in SessionStatus]
if new_status not in valid_statuses:
raise ValueError(f"无效的会话状态: {new_status}")
self.status = new_status
self.updated_at = datetime.now()
def advance_step(self) -> bool:
"""
推进到下一步
Returns:
bool: 是否成功推进
"""
if self.current_step < self.total_steps:
self.current_step += 1
self.updated_at = datetime.now()
# 如果到达最后一步,标记为完成
if self.current_step == self.total_steps:
self.status = SessionStatus.COMPLETED.value
return True
return False
def reset_step(self, step_number: int) -> bool:
"""
重置到指定步骤
Args:
step_number: 目标步骤号
Returns:
bool: 是否成功重置
"""
if 1 <= step_number <= self.total_steps:
self.current_step = step_number
self.updated_at = datetime.now()
# 如果从完成状态回退,更新状态
if self.status == SessionStatus.COMPLETED.value and step_number < self.total_steps:
self.status = SessionStatus.ACTIVE.value
return True
return False
def update_setting(self, key: str, value: Any) -> None:
"""
更新设置项
Args:
key: 设置键
value: 设置值
"""
self.settings[key] = value
self.updated_at = datetime.now()
def add_metadata(self, key: str, value: Any) -> None:
"""
添加元数据
Args:
key: 元数据键
value: 元数据值
"""
self.metadata[key] = value
self.updated_at = datetime.now()
def add_tag(self, tag: str) -> None:
"""
添加标签
Args:
tag: 标签名称
"""
if 'tags' not in self.metadata:
self.metadata['tags'] = []
if tag not in self.metadata['tags']:
self.metadata['tags'].append(tag)
self.updated_at = datetime.now()
def remove_tag(self, tag: str) -> bool:
"""
移除标签
Args:
tag: 标签名称
Returns:
bool: 是否成功移除
"""
if 'tags' in self.metadata and tag in self.metadata['tags']:
self.metadata['tags'].remove(tag)
self.updated_at = datetime.now()
return True
return False
def extend_expiry(self, days: int = 7) -> None:
"""
延长过期时间
Args:
days: 延长天数
"""
self.expires_at = datetime.now() + timedelta(days=days)
self.updated_at = datetime.now()
def is_expired(self) -> bool:
"""
检查是否已过期
Returns:
bool: 是否已过期
"""
return datetime.now() > self.expires_at
def is_active(self) -> bool:
"""
检查是否处于活跃状态
Returns:
bool: 是否活跃
"""
return self.status == SessionStatus.ACTIVE.value and not self.is_expired()
def is_completed(self) -> bool:
"""
检查是否已完成
Returns:
bool: 是否已完成
"""
return self.status == SessionStatus.COMPLETED.value or self.current_step >= self.total_steps
def get_progress_percentage(self) -> float:
"""
获取进度百分比
Returns:
float: 进度百分比 (0-100)
"""
if self.total_steps <= 0:
return 0.0
return min(100.0, (self.current_step / self.total_steps) * 100.0)
def get_remaining_steps(self) -> int:
"""
获取剩余步骤数
Returns:
int: 剩余步骤数
"""
return max(0, self.total_steps - self.current_step)
def get_session_duration(self) -> timedelta:
"""
获取会话持续时间
Returns:
timedelta: 持续时间
"""
return self.updated_at - self.created_at
def __str__(self) -> str:
"""
字符串表示
Returns:
str: 字符串描述
"""
return f"SessionModel(id={self.session_id}, user={self.user_id}, step={self.current_step}/{self.total_steps}, status={self.status})"
def __repr__(self) -> str:
"""
详细字符串表示
Returns:
str: 详细描述
"""
return (f"SessionModel(session_id={self.session_id}, user_id={self.user_id}, "
f"type={self.session_type}, title='{self.title}', status={self.status}, "
f"step={self.current_step}/{self.total_steps}, created={self.created_at})")

397
models/session_model.py Normal file
View File

@ -0,0 +1,397 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
会话数据模型
定义会话的数据结构和验证逻辑
"""
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, field
from enum import Enum
class SessionStatus(Enum):
"""会话状态枚举"""
QUEUED = "queued" # 排队中
PENDING = "pending" # 等待中
ACTIVE = "active" # 活跃状态
PAUSED = "paused" # 暂停状态
COMPLETED = "completed" # 已完成
CANCELLED = "cancelled" # 已取消
ERROR = "error" # 错误状态
class SessionType(Enum):
"""会话类型枚举"""
SCRIPTWRITING = "scriptwriting" # 编剧创作
CONSULTATION = "consultation" # 咨询对话
REVIEW = "review" # 剧本评审
COLLABORATION = "collaboration" # 协作创作
@dataclass
class SessionModel:
"""
会话数据模型
定义会话的完整数据结构
"""
# 基础信息
user_id: str
session_type: str = SessionType.SCRIPTWRITING.value
title: str = ""
description: str = ""
# 原始剧本内容
original_script: str = ""
# 状态信息
status: str = SessionStatus.ACTIVE.value
current_step: int = 1
total_steps: int = 6
# 配置信息
settings: Dict[str, Any] = field(default_factory=dict)
metadata: Dict[str, Any] = field(default_factory=dict)
# 时间信息
created_at: datetime = field(default_factory=datetime.now)
updated_at: datetime = field(default_factory=datetime.now)
expires_at: datetime = field(default_factory=lambda: datetime.now() + timedelta(days=7))
# 可选字段
session_id: Optional[str] = None
def __post_init__(self):
"""初始化后处理"""
# 验证数据
self.validate()
# 设置默认值
if not self.title:
self.title = f"编剧会话 - {self.created_at.strftime('%Y-%m-%d %H:%M')}"
# 确保设置字典存在必要的键
default_settings = {
'auto_save': True,
'step_timeout': 1800, # 30分钟
'max_retries': 3,
'language': 'zh-CN',
'genre': 'drama',
'style': 'modern'
}
for key, value in default_settings.items():
if key not in self.settings:
self.settings[key] = value
# 确保元数据字典存在
if 'tags' not in self.metadata:
self.metadata['tags'] = []
if 'source' not in self.metadata:
self.metadata['source'] = 'web_interface'
def validate(self) -> bool:
"""
验证数据有效性
Returns:
bool: 是否有效
Raises:
ValueError: 数据无效时抛出异常
"""
# 验证用户ID
if not self.user_id or not isinstance(self.user_id, str):
raise ValueError("用户ID不能为空且必须是字符串")
# 验证会话类型
valid_types = [t.value for t in SessionType]
if self.session_type not in valid_types:
raise ValueError(f"无效的会话类型: {self.session_type},有效值: {valid_types}")
# 验证状态
valid_statuses = [s.value for s in SessionStatus]
if self.status not in valid_statuses:
raise ValueError(f"无效的会话状态: {self.status},有效值: {valid_statuses}")
# 验证步骤
if not isinstance(self.current_step, int) or self.current_step < 1:
raise ValueError("当前步骤必须是大于0的整数")
if not isinstance(self.total_steps, int) or self.total_steps < 1:
raise ValueError("总步骤数必须是大于0的整数")
if self.current_step > self.total_steps:
raise ValueError("当前步骤不能超过总步骤数")
# 验证时间
if self.updated_at < self.created_at:
raise ValueError("更新时间不能早于创建时间")
if self.expires_at <= self.created_at:
raise ValueError("过期时间必须晚于创建时间")
return True
def to_dict(self) -> Dict[str, Any]:
"""
转换为字典格式
Returns:
Dict: 字典数据
"""
data = {
'user_id': self.user_id,
'session_type': self.session_type,
'title': self.title,
'description': self.description,
'original_script': self.original_script,
'status': self.status,
'current_step': self.current_step,
'total_steps': self.total_steps,
'settings': self.settings.copy(),
'metadata': self.metadata.copy(),
'created_at': self.created_at,
'updated_at': self.updated_at,
'expires_at': self.expires_at
}
if self.session_id:
data['session_id'] = self.session_id
return data
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> 'SessionModel':
"""
从字典创建模型实例
Args:
data: 字典数据
Returns:
SessionModel: 模型实例
"""
# 提取必需字段
user_id = data.get('user_id')
if not user_id:
raise ValueError("缺少必需字段: user_id")
# 创建实例
instance = cls(
user_id=user_id,
session_type=data.get('session_type', SessionType.SCRIPTWRITING.value),
title=data.get('title', ''),
description=data.get('description', ''),
status=data.get('status', SessionStatus.ACTIVE.value),
current_step=data.get('current_step', 1),
total_steps=data.get('total_steps', 6),
settings=data.get('settings', {}),
metadata=data.get('metadata', {})
)
# 设置时间字段
if 'created_at' in data:
instance.created_at = data['created_at']
if 'updated_at' in data:
instance.updated_at = data['updated_at']
if 'expires_at' in data:
instance.expires_at = data['expires_at']
# 设置可选字段
if 'session_id' in data:
instance.session_id = data['session_id']
return instance
def update_status(self, new_status: str) -> None:
"""
更新会话状态
Args:
new_status: 新状态
"""
valid_statuses = [s.value for s in SessionStatus]
if new_status not in valid_statuses:
raise ValueError(f"无效的会话状态: {new_status}")
self.status = new_status
self.updated_at = datetime.now()
def advance_step(self) -> bool:
"""
推进到下一步
Returns:
bool: 是否成功推进
"""
if self.current_step < self.total_steps:
self.current_step += 1
self.updated_at = datetime.now()
# 如果到达最后一步,标记为完成
if self.current_step == self.total_steps:
self.status = SessionStatus.COMPLETED.value
return True
return False
def reset_step(self, step_number: int) -> bool:
"""
重置到指定步骤
Args:
step_number: 目标步骤号
Returns:
bool: 是否成功重置
"""
if 1 <= step_number <= self.total_steps:
self.current_step = step_number
self.updated_at = datetime.now()
# 如果从完成状态回退,更新状态
if self.status == SessionStatus.COMPLETED.value and step_number < self.total_steps:
self.status = SessionStatus.ACTIVE.value
return True
return False
def update_setting(self, key: str, value: Any) -> None:
"""
更新设置项
Args:
key: 设置键
value: 设置值
"""
self.settings[key] = value
self.updated_at = datetime.now()
def add_metadata(self, key: str, value: Any) -> None:
"""
添加元数据
Args:
key: 元数据键
value: 元数据值
"""
self.metadata[key] = value
self.updated_at = datetime.now()
def add_tag(self, tag: str) -> None:
"""
添加标签
Args:
tag: 标签名称
"""
if 'tags' not in self.metadata:
self.metadata['tags'] = []
if tag not in self.metadata['tags']:
self.metadata['tags'].append(tag)
self.updated_at = datetime.now()
def remove_tag(self, tag: str) -> bool:
"""
移除标签
Args:
tag: 标签名称
Returns:
bool: 是否成功移除
"""
if 'tags' in self.metadata and tag in self.metadata['tags']:
self.metadata['tags'].remove(tag)
self.updated_at = datetime.now()
return True
return False
def extend_expiry(self, days: int = 7) -> None:
"""
延长过期时间
Args:
days: 延长天数
"""
self.expires_at = datetime.now() + timedelta(days=days)
self.updated_at = datetime.now()
def is_expired(self) -> bool:
"""
检查是否已过期
Returns:
bool: 是否已过期
"""
return datetime.now() > self.expires_at
def is_active(self) -> bool:
"""
检查是否处于活跃状态
Returns:
bool: 是否活跃
"""
return self.status == SessionStatus.ACTIVE.value and not self.is_expired()
def is_completed(self) -> bool:
"""
检查是否已完成
Returns:
bool: 是否已完成
"""
return self.status == SessionStatus.COMPLETED.value or self.current_step >= self.total_steps
def get_progress_percentage(self) -> float:
"""
获取进度百分比
Returns:
float: 进度百分比 (0-100)
"""
if self.total_steps <= 0:
return 0.0
return min(100.0, (self.current_step / self.total_steps) * 100.0)
def get_remaining_steps(self) -> int:
"""
获取剩余步骤数
Returns:
int: 剩余步骤数
"""
return max(0, self.total_steps - self.current_step)
def get_session_duration(self) -> timedelta:
"""
获取会话持续时间
Returns:
timedelta: 持续时间
"""
return self.updated_at - self.created_at
def __str__(self) -> str:
"""
字符串表示
Returns:
str: 字符串描述
"""
return f"SessionModel(id={self.session_id}, user={self.user_id}, step={self.current_step}/{self.total_steps}, status={self.status})"
def __repr__(self) -> str:
"""
详细字符串表示
Returns:
str: 详细描述
"""
return (f"SessionModel(session_id={self.session_id}, user_id={self.user_id}, "
f"type={self.session_type}, title='{self.title}', status={self.status}, "
f"step={self.current_step}/{self.total_steps}, created={self.created_at})")

10
pyrightconfig.json Normal file
View File

@ -0,0 +1,10 @@
{
"typeCheckingMode": "basic",
"reportUnknownMemberType": false,
"reportUnknownVariableType": false,
"reportUnknownArgumentType": false,
"reportMissingParameterType": false,
"reportMissingTypeArgument": false,
"reportUnknownParameterType": false,
"reportImplicitRelativeImport": false
}

23
requirements.txt Normal file
View File

@ -0,0 +1,23 @@
Flask
Flask-Cors
pymongo
python-dotenv
PyJWT
Werkzeug
dnspython
requests
oss2
PyPDF2
PyMuPDF
python-docx
openai
Pillow
tos
volcengine-python-sdk[ark]
volcengine[ark]
PyMySQL
DBUtils
PyMuPDF
langchain-community
langgraph
langgraph-checkpoint-mongodb

4
routes/__init__.py Normal file
View File

@ -0,0 +1,4 @@
# routes/__init__.py
"""
路由模块初始化文件
"""

View File

@ -0,0 +1,11 @@
from flask import Blueprint
from handlers.langgraph_handler import run_langgraph, get_task_status, resume_task, visualize_graph
# 创建蓝图
bp = Blueprint('langgraph', __name__, url_prefix='/api/v1/langgraph')
# 定义路由
bp.add_url_rule('/run', view_func=run_langgraph, methods=['POST'])
bp.add_url_rule('/status/<thread_id>', view_func=get_task_status, methods=['GET'])
bp.add_url_rule('/resume/<thread_id>', view_func=resume_task, methods=['POST'])
bp.add_url_rule('/visualize/<thread_id>', view_func=visualize_graph, methods=['GET'])

4
tools/__init__.py Normal file
View File

@ -0,0 +1,4 @@
# tools/__init__.py
"""
工具模块初始化文件
"""

View File

@ -0,0 +1,11 @@
# tools/database/__init__.py
"""
数据库工具模块初始化文件
"""
# 从mongo.py导入常用的类或函数方便其他模块导入
try:
from .mongo import client, mainDB
__all__ = ['client', 'mainDB']
except ImportError:
# 如果mongo模块无法导入不抛出异常保持包的基本功能
pass

106
tools/database/mongo.py Normal file
View File

@ -0,0 +1,106 @@
from pymongo import MongoClient
import config
from pymongo.monitoring import (CommandListener, ServerListener, ConnectionPoolListener,
CommandSucceededEvent, CommandFailedEvent,
ServerHeartbeatStartedEvent, ServerHeartbeatSucceededEvent, ServerHeartbeatFailedEvent,
ConnectionCreatedEvent, ConnectionClosedEvent, ConnectionCheckOutStartedEvent,
ConnectionCheckedOutEvent, ConnectionCheckOutFailedEvent, ConnectionCheckedInEvent)
# 命令事件监听器
class MyCommandListener(CommandListener):
def started(self, event):
# print(f"Command {event.command_name} started on {event.connection_id}")
pass
def succeeded(self, event: CommandSucceededEvent):
# print(f"Command {event.command_name} succeeded in {event.duration_micros} microseconds")
pass
def failed(self, event: CommandFailedEvent):
print(f"Command {event.command_name} failed with error: {event.failure}")
# 服务器事件监听器
class MyServerListener(ServerListener):
def opened(self, event):
print(f"Server {event.server_address} opened")
def description_changed(self, event):
# print(f"Server {event.previous_description.address} description changed to {event.new_description.address}")
pass
def closed(self, event):
print(f"Server {event.server_address} closed")
def heartbeat_started(self, event: ServerHeartbeatStartedEvent):
# print(f"Heartbeat started on server with id: {event.connection_id}")
pass
def heartbeat_succeeded(self, event: ServerHeartbeatSucceededEvent):
# print(f"Heartbeat succeeded on server with id: {event.connection_id}")
pass
def heartbeat_failed(self, event: ServerHeartbeatFailedEvent):
print(f"Heartbeat failed on server with id: {event.connection_id} with error: {event.reply}")
# 连接池事件监听器
class MyPoolListener(ConnectionPoolListener):
def pool_created(self, event):
print(f"Connection pool created for {event.address}")
def pool_cleared(self, event):
print(f"Connection pool cleared for {event.address}")
def pool_closed(self, event):
print(f"Connection pool closed for {event.address}")
def connection_created(self, event: ConnectionCreatedEvent):
print(f"Connection {event.connection_id} created for {event.address}")
def connection_ready(self, event):
print(f"Connection {event.connection_id} ready for {event.address}")
def pool_ready(self, event):
print(f"Connection pool ready for {event.address}")
def connection_closed(self, event: ConnectionClosedEvent):
print(f"Connection {event.connection_id} closed for {event.address}, reason: {event.reason}")
def connection_check_out_started(self, event: ConnectionCheckOutStartedEvent):
# print(f"Connection check out started for {event.address}")
pass
def connection_check_out_failed(self, event: ConnectionCheckOutFailedEvent):
print(f"Connection check out failed for {event.address}, reason: {event.reason}")
def connection_checked_out(self, event: ConnectionCheckedOutEvent):
# print(f"Connection {event.connection_id} checked out for {event.address}")
pass
def connection_checked_in(self, event: ConnectionCheckedInEvent):
# print(f"Connection {event.connection_id} checked in for {event.address}")
pass
# 实例化监听器
command_listener = MyCommandListener()
server_listener = MyServerListener()
pool_listener = MyPoolListener()
all_event_listeners = [command_listener, server_listener, pool_listener]
MONGO_URI = config.MONGO_URI
DB_NAME = config.MONGO_MAIN_DB_NAME
# 创建MongoDB客户端连接
try:
# 实例化MongoClient时传入事件监听器
client = MongoClient(MONGO_URI, event_listeners=all_event_listeners, serverSelectionTimeoutMS=5000) # 设置5秒超时
mainDB = client[DB_NAME]
# 主动检查连接状态
client.admin.command('ping')
success_message = f"\033[92m成功连接到MongoDB: {DB_NAME},事件监听器已激活。\033[0m"
print(success_message)
except Exception as e:
error_message = f"\033[91m数据库连接失败: {MONGO_URI}请检查MongoDB服务是否已启动。\033[0m"
print(error_message)

View File

@ -0,0 +1,30 @@
"""工作流记忆管理模块
该模块负责管理智能编剧系统工作流的记忆存储和检索
"""
import sys
import os
from typing import Dict, Any, List, Optional
from datetime import datetime
import json
from database import client # type: ignore
from langgraph.checkpoint.mongodb import MongoDBSaver
# 添加项目根目录到路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
from agentgraph.utils.logger import get_logger
logger = get_logger(__name__)
DB_NAME = "langgraph_memory_db"
class WorkflowMemory:
"""工作流记忆管理类
负责管理工作流执行过程中的状态存储检索和历史记录
"""
def __init__(self):
"""初始化工作流记忆管理器"""
self.memory = MongoDBSaver(client, db_name=DB_NAME)

9
tools/llm/__init__.py Normal file
View File

@ -0,0 +1,9 @@
# tools/llm/__init__.py
"""
大语言模型工具模块初始化文件
"""
from .huoshan_langchain import HuoshanChatModel
__all__ = [
'HuoshanChatModel'
]

View File

@ -0,0 +1,137 @@
from typing import Any, Dict, Iterator, List, Optional
from langchain_core.callbacks.manager import CallbackManagerForLLMRun
from langchain_core.language_models.chat_models import BaseChatModel
from langchain_core.messages import BaseMessage, AIMessage, HumanMessage, SystemMessage
from langchain_core.outputs import ChatGeneration, ChatResult
from pydantic import Field
from api.huoshan import HuoshanAPI # 导入你现有的API类
class HuoshanChatModel(BaseChatModel):
"""火山引擎聊天模型的LangChain封装"""
# 模型配置参数
model_name: str = Field(default="doubao-seed-1.6-250615", description="模型名称")
temperature: float = Field(default=0.6, description="温度参数")
max_tokens: int = Field(default=16384, description="最大token数")
# 内部API实例
_api: Optional[HuoshanAPI] = None
def __init__(self, **kwargs):
super().__init__(**kwargs)
# 初始化火山引擎API实例
self._api = HuoshanAPI()
@property
def _llm_type(self) -> str:
"""返回LLM类型标识"""
return "huoshan_chat"
def _convert_messages_to_prompt(self, messages: List[BaseMessage]) -> tuple[str, str]:
"""将LangChain消息格式转换为API所需的prompt和system格式"""
system_message = ""
user_messages = []
for message in messages:
if isinstance(message, SystemMessage):
system_message = message.content or ""
elif isinstance(message, HumanMessage):
user_messages.append(message.content)
elif isinstance(message, AIMessage):
# 如果需要支持多轮对话,可以在这里处理
pass
# 合并用户消息
prompt = "\n".join(user_messages) if user_messages else ""
return prompt, str(system_message)
def _generate(
self,
messages: List[BaseMessage],
stop: Optional[List[str]] = None,
run_manager: Optional[CallbackManagerForLLMRun] = None,
**kwargs: Any,
) -> ChatResult:
"""生成聊天回复"""
if not self._api:
raise ValueError("HuoshanAPI未正确初始化")
# 转换消息格式
prompt, system = self._convert_messages_to_prompt(messages)
# 合并参数
generation_kwargs = {
"model": kwargs.get("model", self.model_name),
"temperature": kwargs.get("temperature", self.temperature),
"system": system
}
try:
# 调用你的API
response_text = self._api.get_chat_response(
prompt=prompt,
**generation_kwargs
)
# 创建AI消息
message = AIMessage(content=response_text)
# 创建生成结果
generation = ChatGeneration(message=message)
return ChatResult(generations=[generation])
except Exception as e:
raise ValueError(f"调用火山引擎API失败: {str(e)}")
def _stream(
self,
messages: List[BaseMessage],
stop: Optional[List[str]] = None,
run_manager: Optional[CallbackManagerForLLMRun] = None,
**kwargs: Any,
) -> Iterator[ChatGeneration]:
"""流式生成聊天回复"""
if not self._api:
raise ValueError("HuoshanAPI未正确初始化")
# 转换消息格式
prompt, system = self._convert_messages_to_prompt(messages)
# 合并参数
generation_kwargs = {
"model": kwargs.get("model", self.model_name),
"temperature": kwargs.get("temperature", self.temperature),
"system": system
}
try:
# 调用流式API
for chunk in self._api.get_chat_response_stream(
prompt=prompt,
**generation_kwargs
):
if chunk:
# 创建增量消息
message = AIMessage(content=chunk)
generation = ChatGeneration(message=message)
# 如果有回调管理器通知新token
if run_manager:
run_manager.on_llm_new_token(chunk)
yield generation
except Exception as e:
raise ValueError(f"调用火山引擎流式API失败: {str(e)}")
@property
def _identifying_params(self) -> Dict[str, Any]:
"""返回用于标识模型的参数"""
return {
"model_name": self.model_name,
"temperature": self.temperature,
"max_tokens": self.max_tokens,
}

0
utils/__init__.py Normal file
View File

655
utils/formatters.py Normal file
View File

@ -0,0 +1,655 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
格式化器模块
提供响应格式化数据转换和输出格式化功能
"""
import json
from datetime import datetime, date
from typing import Dict, List, Optional, Any, Union
from decimal import Decimal
class ResponseFormatter:
"""响应格式化器"""
@staticmethod
def success_response(data: Any = None, message: str = "操作成功",
code: int = 200, extra: Dict[str, Any] = {}) -> Dict[str, Any]:
"""
创建成功响应
Args:
data: 响应数据
message: 响应消息
code: 状态码
extra: 额外信息
Returns:
Dict: 格式化的响应
"""
response = {
"success": True,
"code": code,
"message": message,
"timestamp": datetime.now().isoformat(),
"data": data
}
if extra:
response.update(extra)
return response
@staticmethod
def error_response(message: str = "操作失败", code: int = 400,
error_type: str = "ValidationError",
details: Dict[str, Any] = {}) -> Dict[str, Any]:
"""
创建错误响应
Args:
message: 错误消息
code: 错误码
error_type: 错误类型
details: 错误详情
Returns:
Dict: 格式化的错误响应
"""
response = {
"success": False,
"code": code,
"message": message,
"error_type": error_type,
"timestamp": datetime.now().isoformat()
}
if details:
response["details"] = details
return response
@staticmethod
def paginated_response(items: List[Any], total: int, page: int,
page_size: int, message: str = "查询成功") -> Dict[str, Any]:
"""
创建分页响应
Args:
items: 数据项列表
total: 总数量
page: 当前页码
page_size: 页大小
message: 响应消息
Returns:
Dict: 格式化的分页响应
"""
total_pages = (total + page_size - 1) // page_size
pagination = {
"current_page": page,
"page_size": page_size,
"total_items": total,
"total_pages": total_pages,
"has_next": page < total_pages,
"has_prev": page > 1
}
return ResponseFormatter.success_response(
data={
"items": items,
"pagination": pagination
},
message=message
)
@staticmethod
def stream_response(data: Any, event_type: str = "data",
event_id: str = "") -> str:
"""
创建流式响应
Args:
data: 响应数据
event_type: 事件类型
event_id: 事件ID
Returns:
str: SSE格式的响应
"""
lines = []
if event_id:
lines.append(f"id: {event_id}")
lines.append(f"event: {event_type}")
# 将数据转换为JSON字符串
if isinstance(data, (dict, list)):
data_str = json.dumps(data, ensure_ascii=False, cls=DateTimeEncoder)
else:
data_str = str(data)
lines.append(f"data: {data_str}")
lines.append("") # 空行表示事件结束
return "\n".join(lines)
@staticmethod
def validation_error_response(errors: List[str],
warnings: List[str] = []) -> Dict[str, Any]:
"""
创建验证错误响应
Args:
errors: 错误列表
warnings: 警告列表
Returns:
Dict: 格式化的验证错误响应
"""
details = {"errors": errors}
if warnings:
details["warnings"] = warnings
return ResponseFormatter.error_response(
message="数据验证失败",
code=422,
error_type="ValidationError",
details=details
)
@staticmethod
def not_found_response(resource: str = "资源") -> Dict[str, Any]:
"""
创建资源未找到响应
Args:
resource: 资源名称
Returns:
Dict: 格式化的未找到响应
"""
return ResponseFormatter.error_response(
message=f"{resource}未找到",
code=404,
error_type="NotFoundError"
)
@staticmethod
def unauthorized_response(message: str = "未授权访问") -> Dict[str, Any]:
"""
创建未授权响应
Args:
message: 错误消息
Returns:
Dict: 格式化的未授权响应
"""
return ResponseFormatter.error_response(
message=message,
code=401,
error_type="UnauthorizedError"
)
@staticmethod
def forbidden_response(message: str = "禁止访问") -> Dict[str, Any]:
"""
创建禁止访问响应
Args:
message: 错误消息
Returns:
Dict: 格式化的禁止访问响应
"""
return ResponseFormatter.error_response(
message=message,
code=403,
error_type="ForbiddenError"
)
@staticmethod
def rate_limit_response(retry_after: int = 60) -> Dict[str, Any]:
"""
创建限流响应
Args:
retry_after: 重试等待时间
Returns:
Dict: 格式化的限流响应
"""
return ResponseFormatter.error_response(
message="请求过于频繁,请稍后重试",
code=429,
error_type="RateLimitError",
details={"retry_after": retry_after}
)
@staticmethod
def server_error_response(message: str = "服务器内部错误") -> Dict[str, Any]:
"""
创建服务器错误响应
Args:
message: 错误消息
Returns:
Dict: 格式化的服务器错误响应
"""
return ResponseFormatter.error_response(
message=message,
code=500,
error_type="InternalServerError"
)
class ErrorFormatter:
"""错误格式化器"""
@staticmethod
def format_exception(exception: Exception, include_traceback: bool = False) -> Dict[str, Any]:
"""
格式化异常信息
Args:
exception: 异常对象
include_traceback: 是否包含堆栈跟踪
Returns:
Dict: 格式化的异常信息
"""
error_info = {
"type": exception.__class__.__name__,
"message": str(exception),
"timestamp": datetime.now().isoformat()
}
if include_traceback:
import traceback
error_info["traceback"] = traceback.format_exc()
return error_info
@staticmethod
def format_validation_errors(errors: List[str], field_errors: Dict[str, List[str]] = {}) -> Dict[str, Any]:
"""
格式化验证错误
Args:
errors: 通用错误列表
field_errors: 字段特定错误字典
Returns:
Dict: 格式化的验证错误
"""
formatted = {
"general_errors": errors,
"error_count": len(errors)
}
if field_errors:
formatted["field_errors"] = field_errors
formatted["error_count"] += sum(len(errs) for errs in field_errors.values())
return formatted
@staticmethod
def format_database_error(error: Exception) -> Dict[str, Any]:
"""
格式化数据库错误
Args:
error: 数据库异常
Returns:
Dict: 格式化的数据库错误
"""
error_message = str(error)
# 根据错误类型提供更友好的消息
if "duplicate key" in error_message.lower():
user_message = "数据已存在,请检查唯一性约束"
elif "foreign key" in error_message.lower():
user_message = "关联数据不存在,请检查数据完整性"
elif "not null" in error_message.lower():
user_message = "必填字段不能为空"
elif "timeout" in error_message.lower():
user_message = "数据库操作超时,请稍后重试"
else:
user_message = "数据库操作失败"
return {
"type": "DatabaseError",
"user_message": user_message,
"technical_message": error_message,
"timestamp": datetime.now().isoformat()
}
class DataFormatter:
"""数据格式化器"""
@staticmethod
def format_session_data(session_data: Dict[str, Any]) -> Dict[str, Any]:
"""
格式化会话数据
Args:
session_data: 原始会话数据
Returns:
Dict: 格式化的会话数据
"""
formatted = {
"session_id": session_data.get("session_id"),
"user_id": session_data.get("user_id"),
"session_type": session_data.get("session_type"),
"status": session_data.get("status"),
"current_step": session_data.get("current_step", 1),
"created_at": DataFormatter._format_datetime(session_data.get("created_at")),
"updated_at": DataFormatter._format_datetime(session_data.get("updated_at")),
"expires_at": DataFormatter._format_datetime(session_data.get("expires_at"))
}
# 添加可选字段
optional_fields = ["title", "description", "session_config", "metadata"]
for field in optional_fields:
if field in session_data:
formatted[field] = session_data[field]
return formatted
@staticmethod
def format_step_data(step_data: Dict[str, Any]) -> Dict[str, Any]:
"""
格式化步骤数据
Args:
step_data: 原始步骤数据
Returns:
Dict: 格式化的步骤数据
"""
formatted = {
"step_id": step_data.get("step_id"),
"session_id": step_data.get("session_id"),
"step_number": step_data.get("step_number"),
"step_type": step_data.get("step_type"),
"status": step_data.get("status"),
"execution_mode": step_data.get("execution_mode", "sync"),
"started_at": DataFormatter._format_datetime(step_data.get("started_at")),
"completed_at": DataFormatter._format_datetime(step_data.get("completed_at")),
"created_at": DataFormatter._format_datetime(step_data.get("created_at"))
}
# 添加执行结果
if "result_data" in step_data:
formatted["result_data"] = step_data["result_data"]
# 添加错误信息
if "error_message" in step_data:
formatted["error_message"] = step_data["error_message"]
# 计算执行时长
if step_data.get("started_at") and step_data.get("completed_at"):
start_time = step_data["started_at"]
end_time = step_data["completed_at"]
if isinstance(start_time, datetime) and isinstance(end_time, datetime):
duration = (end_time - start_time).total_seconds()
formatted["execution_duration_seconds"] = duration
return formatted
@staticmethod
def format_workflow_state_data(state_data: Dict[str, Any]) -> Dict[str, Any]:
"""
格式化工作流状态数据
Args:
state_data: 原始状态数据
Returns:
Dict: 格式化的状态数据
"""
formatted = {
"state_id": state_data.get("state_id"),
"session_id": state_data.get("session_id"),
"state_type": state_data.get("state_type"),
"status": state_data.get("status"),
"priority": state_data.get("priority"),
"created_at": DataFormatter._format_datetime(state_data.get("created_at")),
"updated_at": DataFormatter._format_datetime(state_data.get("updated_at")),
"expires_at": DataFormatter._format_datetime(state_data.get("expires_at"))
}
# 添加状态特定数据
if "state_data" in state_data:
formatted["state_data"] = state_data["state_data"]
# 添加可选字段
optional_fields = ["category", "related_step", "assigned_to", "processed_by", "processed_at"]
for field in optional_fields:
if field in state_data:
if field == "processed_at":
formatted[field] = DataFormatter._format_datetime(state_data[field])
else:
formatted[field] = state_data[field]
return formatted
@staticmethod
def format_memory_data(memory_data: Dict[str, Any]) -> Dict[str, Any]:
"""
格式化记忆数据
Args:
memory_data: 原始记忆数据
Returns:
Dict: 格式化的记忆数据
"""
formatted = {
"memory_id": memory_data.get("memory_id"),
"user_id": memory_data.get("user_id"),
"memory_type": memory_data.get("memory_type"),
"memory_key": memory_data.get("memory_key"),
"category": memory_data.get("category"),
"access_level": memory_data.get("access_level"),
"importance": memory_data.get("importance"),
"weight": memory_data.get("weight"),
"access_count": memory_data.get("access_count", 0),
"created_at": DataFormatter._format_datetime(memory_data.get("created_at")),
"updated_at": DataFormatter._format_datetime(memory_data.get("updated_at"))
}
# 添加记忆数据(可能需要脱敏)
if "memory_data" in memory_data:
formatted["memory_data"] = DataFormatter._sanitize_memory_data(
memory_data["memory_data"],
memory_data.get("sensitivity", "low")
)
# 添加可选字段
optional_fields = ["description", "tags", "last_accessed", "expires_at"]
for field in optional_fields:
if field in memory_data:
if field in ["last_accessed", "expires_at"]:
formatted[field] = DataFormatter._format_datetime(memory_data[field])
else:
formatted[field] = memory_data[field]
return formatted
@staticmethod
def format_list_response(items: List[Dict[str, Any]],
formatter_func,
total: int = 0,
page: int = 0,
page_size: int = 0) -> Dict[str, Any]:
"""
格式化列表响应
Args:
items: 数据项列表
formatter_func: 格式化函数
total: 总数量
page: 页码
page_size: 页大小
Returns:
Dict: 格式化的列表响应
"""
formatted_items = [formatter_func(item) for item in items]
result:Any = {"items": formatted_items}
if total > 0:
result["total"] = total
if page > 0 and page_size > 0:
result["pagination"] = {
"current_page": page,
"page_size": page_size,
"total_pages": (total + page_size - 1) // page_size if total else 1
}
return result
@staticmethod
def _format_datetime(dt: Union[datetime, str, None]) -> Optional[str]:
"""
格式化日期时间
Args:
dt: 日期时间对象或字符串
Returns:
Optional[str]: 格式化的日期时间字符串
"""
if dt is None:
return None
if isinstance(dt, datetime):
return dt.isoformat()
if isinstance(dt, str):
return dt
return str(dt)
@staticmethod
def _sanitize_memory_data(memory_data: Dict[str, Any], sensitivity: str) -> Dict[str, Any]:
"""
根据敏感度脱敏记忆数据
Args:
memory_data: 记忆数据
sensitivity: 敏感度级别
Returns:
Dict: 脱敏后的数据
"""
if sensitivity in ["high", "confidential"]:
# 高敏感度数据需要脱敏
sanitized = {}
for key, value in memory_data.items():
if key in ["password", "token", "secret", "private_key"]:
sanitized[key] = "***"
elif isinstance(value, str) and len(value) > 10:
# 长字符串部分脱敏
sanitized[key] = value[:3] + "***" + value[-3:]
else:
sanitized[key] = value
return sanitized
return memory_data.copy()
class DateTimeEncoder(json.JSONEncoder):
"""自定义JSON编码器处理日期时间对象"""
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
elif isinstance(obj, date):
return obj.isoformat()
elif isinstance(obj, Decimal):
return float(obj)
return super().default(obj)
def format_file_size(size_bytes: int) -> str:
"""
格式化文件大小
Args:
size_bytes: 字节数
Returns:
str: 格式化的文件大小
"""
if size_bytes == 0:
return "0 B"
size_names = ["B", "KB", "MB", "GB", "TB"]
import math
i = int(math.floor(math.log(size_bytes, 1024)))
p = math.pow(1024, i)
s = round(size_bytes / p, 2)
return f"{s} {size_names[i]}"
def format_duration(seconds: float) -> str:
"""
格式化持续时间
Args:
seconds: 秒数
Returns:
str: 格式化的持续时间
"""
if seconds < 60:
return f"{seconds:.2f}"
elif seconds < 3600:
minutes = seconds / 60
return f"{minutes:.2f}分钟"
else:
hours = seconds / 3600
return f"{hours:.2f}小时"
def truncate_text(text: str, max_length: int = 100, suffix: str = "...") -> str:
"""
截断文本
Args:
text: 原始文本
max_length: 最大长度
suffix: 后缀
Returns:
str: 截断后的文本
"""
if len(text) <= max_length:
return text
return text[:max_length - len(suffix)] + suffix
def mask_sensitive_info(text: str, mask_char: str = "*", visible_chars: int = 3) -> str:
"""
遮蔽敏感信息
Args:
text: 原始文本
mask_char: 遮蔽字符
visible_chars: 可见字符数
Returns:
str: 遮蔽后的文本
"""
if len(text) <= visible_chars * 2:
return mask_char * len(text)
return text[:visible_chars] + mask_char * (len(text) - visible_chars * 2) + text[-visible_chars:]

58
utils/logger.py Normal file
View File

@ -0,0 +1,58 @@
import logging
import os
import sys
from logging.handlers import RotatingFileHandler
def get_logger(name):
"""
获取统一配置的logger实例
Args:
name: logger名称通常使用 __name__
Returns:
logging.Logger: 配置好的logger实例
"""
logger = logging.getLogger(name)
# 如果logger已经配置过直接返回
if logger.handlers:
return logger
# 设置日志级别
logger.setLevel(logging.INFO)
# 创建日志目录
log_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'logs')
os.makedirs(log_dir, exist_ok=True)
# 创建日志格式
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 文件处理器 - 使用轮转日志
log_file = os.path.join(log_dir, 'langgraph.log')
file_handler = RotatingFileHandler(
log_file,
maxBytes=10*1024*1024, # 10MB
backupCount=5,
encoding='utf-8'
)
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
# 控制台处理器
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(formatter)
# 添加处理器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 防止日志向上传播
logger.propagate = False
return logger