test
This commit is contained in:
+6
-18
@@ -501,11 +501,9 @@ def summarize_recent_chapters(
|
||||
)
|
||||
|
||||
combined_text = "\n".join(chapters_text_list)
|
||||
prompt = f"""你是一名资深长篇小说写作辅助AI,下面是最近几章的合并文本:
|
||||
{combined_text}
|
||||
prompt = f"""你是一名资深长篇小说编辑,分析以下合并文本:\n\n {combined_text} \n\n
|
||||
|
||||
请用中文输出不超过1000字的摘要,只包含主要剧情进展、角色变化、冲突焦点等要点:
|
||||
重点强调最后一章的重要内容,以及最后一幕场景细节。
|
||||
从中提取并预测下一章节的关键字[关键物品/人物/地点/事件/情节]
|
||||
"""
|
||||
|
||||
summary_text = invoke_with_cleaning(model, prompt)
|
||||
@@ -622,16 +620,7 @@ def generate_chapter_draft(
|
||||
if not relevant_context.strip():
|
||||
relevant_context = "(无检索到的上下文)"
|
||||
|
||||
# 5) 构造prompt
|
||||
# 拆分 world_building_text, novel_architecture_text 等等
|
||||
world_building_text = ""
|
||||
match_world = re.search(r'#=== 3\) 世界观 ===\n([\s\S]+?)\n#===', novel_architecture_text)
|
||||
if match_world:
|
||||
world_building_text = match_world.group(1).strip()
|
||||
else:
|
||||
world_building_text = "暂无世界观信息"
|
||||
|
||||
novel_setting_text = novel_architecture_text # 整份当做“小说设定”参考
|
||||
novel_setting_text = novel_architecture_text
|
||||
|
||||
prompt_text = scene_dynamics_prompt.format(
|
||||
novel_number=novel_number,
|
||||
@@ -648,7 +637,6 @@ def generate_chapter_draft(
|
||||
scene_location=scene_location,
|
||||
time_constraint=time_constraint,
|
||||
|
||||
world_building=world_building_text,
|
||||
novel_setting=novel_setting_text,
|
||||
global_summary=global_summary_text,
|
||||
character_state=character_state_text
|
||||
@@ -656,7 +644,7 @@ def generate_chapter_draft(
|
||||
|
||||
# 合并检索到的上下文和用户指导
|
||||
prompt_text += f"\n\n【检索到的上下文】\n{relevant_context}"
|
||||
prompt_text += f"\n\n【用户指导】\n{user_guidance}\n"
|
||||
prompt_text += f"\n\n【章节额外指导】\n{user_guidance}\n"
|
||||
|
||||
model = ChatOpenAI(
|
||||
model=model_name,
|
||||
@@ -847,7 +835,7 @@ def import_knowledge_file(
|
||||
# 尝试加载已有的向量库
|
||||
store = load_vector_store(
|
||||
api_key=embedding_api_key,
|
||||
base_url=embedding_url if embedding_url else "http://localhost:11434/v1",
|
||||
base_url=embedding_url if embedding_url else "http://localhost:11434/api",
|
||||
interface_format=embedding_interface_format,
|
||||
embedding_model_name=embedding_model_name,
|
||||
filepath=filepath
|
||||
@@ -856,7 +844,7 @@ def import_knowledge_file(
|
||||
logging.info("Vector store does not exist. Initializing a new one for knowledge import...")
|
||||
init_vector_store(
|
||||
api_key=embedding_api_key,
|
||||
base_url=embedding_url if embedding_url else "http://localhost:11434/v1",
|
||||
base_url=embedding_url if embedding_url else "http://localhost:11434/api",
|
||||
interface_format=embedding_interface_format,
|
||||
embedding_model_name=embedding_model_name,
|
||||
texts=paragraphs,
|
||||
|
||||
+48
-14
@@ -83,19 +83,19 @@ plot_architecture_prompt = """\
|
||||
世界观:{world_building}
|
||||
|
||||
要求按以下结构设计:
|
||||
▶ 第一幕(触发)
|
||||
第一幕(触发)
|
||||
- 日常状态中的异常征兆(3处铺垫)
|
||||
- 引出故事:展示主线、暗线、副线的开端
|
||||
- 关键事件:打破平衡的催化剂(需改变至少3个角色的关系)
|
||||
- 错误抉择:主角的认知局限导致的错误反应
|
||||
|
||||
▶ 第二幕(对抗)
|
||||
第二幕(对抗)
|
||||
- 剧情升级:主线+副线的交叉点
|
||||
- 双重压力:外部障碍升级+内部挫折
|
||||
- 虚假胜利:看似解决实则深化危机的转折点
|
||||
- 灵魂黑夜:世界观认知颠覆时刻
|
||||
|
||||
▶ 第三幕(解决)
|
||||
第三幕(解决)
|
||||
- 代价显现:解决危机必须牺牲的核心价值
|
||||
- 嵌套转折:至少包含三层认知颠覆(表面解→新危机→终极抉择)
|
||||
- 余波:留下2个开放式悬念因子
|
||||
@@ -169,12 +169,43 @@ update_character_state_prompt = """\
|
||||
{old_state}
|
||||
|
||||
请更新角色状态,内容包括:
|
||||
角色属性:
|
||||
- 角色物品
|
||||
- 能力
|
||||
- 状态
|
||||
- 主要角色间关系网
|
||||
- 触发或加深的事件
|
||||
角色A属性:
|
||||
├──物品:
|
||||
├──道具1:描述
|
||||
├──道具2:描述
|
||||
...
|
||||
├──能力
|
||||
├──技能1:描述
|
||||
├──技能2:描述
|
||||
...
|
||||
├──状态
|
||||
├──身体状态:
|
||||
├──Buff/Debuff
|
||||
├──心理状态:描述
|
||||
|
||||
├──主要角色间关系网
|
||||
├──角色B:描述
|
||||
├──角色C:描述
|
||||
...
|
||||
├──触发或加深的事件
|
||||
├──事件1:描述
|
||||
├──事件2:描述
|
||||
...
|
||||
|
||||
角色B属性:
|
||||
├──物品
|
||||
├──...
|
||||
├──能力
|
||||
├──...
|
||||
├──状态
|
||||
├──...
|
||||
├──主要角色间关系网
|
||||
├──...
|
||||
├──触发或加深的事件
|
||||
├──...
|
||||
|
||||
角色C属性:
|
||||
......
|
||||
|
||||
新出场角色:
|
||||
- 任何新增角色或临时出场人物的基本信息
|
||||
@@ -203,10 +234,13 @@ scene_dynamics_prompt = """\
|
||||
- 时间压力(可能未指定):{time_constraint}
|
||||
|
||||
参考文档:
|
||||
- 世界观:{world_building}
|
||||
- 小说设定:{novel_setting}
|
||||
- 全局摘要:{global_summary}
|
||||
- 角色状态:{character_state}
|
||||
- 小说设定:\n{novel_setting}\n
|
||||
- 全局摘要:\n{global_summary}\n
|
||||
- 角色状态:\n{character_state}\n
|
||||
|
||||
前章片段(可能为空):\n{previous_chapter_excerpt}\n
|
||||
|
||||
本地向量库检索到的上下文片段(可能为空):\n{context_excerpt}\n
|
||||
|
||||
请完成第 {novel_number} 章的正文,至少设计下方2个具有动态张力的场景:
|
||||
1. 对话场景:
|
||||
@@ -224,7 +258,7 @@ scene_dynamics_prompt = """\
|
||||
- 隐喻系统的运用(连接世界观符号)
|
||||
- 决策前的价值天平描写
|
||||
|
||||
最后设置一个"钩链转折":结尾同时回收旧悬念/创造新悬念/抛出新危机/颠覆某个认知预设/神转折等。
|
||||
文末设置一个"钩链转折":结尾时回收旧悬念/创造新悬念/抛出新危机/颠覆某个认知预设/神转折等。
|
||||
|
||||
格式要求:
|
||||
- 仅返回章节正文文本;
|
||||
|
||||
@@ -208,9 +208,12 @@ class NovelGeneratorGUI:
|
||||
|
||||
def build_ai_config_tab(self):
|
||||
def on_interface_format_changed(new_value):
|
||||
if new_value == "OpenAI":
|
||||
if new_value == "Ollama":
|
||||
self.base_url_var.set("http://localhost:11434/v1")
|
||||
elif new_value == "ML Studio":
|
||||
self.base_url_var.set("http://localhost:1234/v1")
|
||||
elif new_value == "OpenAI":
|
||||
self.base_url_var.set("https://api.openai.com/v1")
|
||||
# 可根据需要扩展 Ollama / ML Studio 等
|
||||
|
||||
for i in range(5):
|
||||
self.ai_config_tab.grid_rowconfigure(i, weight=0)
|
||||
@@ -230,7 +233,7 @@ class NovelGeneratorGUI:
|
||||
|
||||
interface_label = ctk.CTkLabel(self.ai_config_tab, text="LLM 接口格式:", font=("Microsoft YaHei", 12))
|
||||
interface_label.grid(row=2, column=0, padx=5, pady=5, sticky="e")
|
||||
interface_options = ["OpenAI"]
|
||||
interface_options = ["OpenAI", "Ollama", "ML Studio"]
|
||||
interface_dropdown = ctk.CTkOptionMenu(
|
||||
self.ai_config_tab,
|
||||
values=interface_options,
|
||||
@@ -268,6 +271,14 @@ class NovelGeneratorGUI:
|
||||
self.temp_value_label.grid(row=4, column=2, padx=1, pady=1, sticky="w")
|
||||
|
||||
def build_embeddings_config_tab(self):
|
||||
def on_embedding_interface_changed(new_value):
|
||||
if new_value == "Ollama":
|
||||
self.embedding_url_var.set("http://localhost:11434/api")
|
||||
elif new_value == "ML Studio":
|
||||
self.embedding_url_var.set("http://localhost:1234/v1")
|
||||
elif new_value == "OpenAI":
|
||||
self.embedding_url_var.set("https://api.openai.com/v1")
|
||||
|
||||
for i in range(5):
|
||||
self.embeddings_config_tab.grid_rowconfigure(i, weight=0)
|
||||
self.embeddings_config_tab.grid_columnconfigure(0, weight=0)
|
||||
@@ -280,11 +291,12 @@ class NovelGeneratorGUI:
|
||||
|
||||
emb_interface_label = ctk.CTkLabel(self.embeddings_config_tab, text="Embedding 接口格式:", font=("Microsoft YaHei", 12))
|
||||
emb_interface_label.grid(row=1, column=0, padx=5, pady=5, sticky="e")
|
||||
emb_interface_options = ["OpenAI"] # 可扩展
|
||||
emb_interface_options = ["OpenAI", "Ollama", "ML Studio"]
|
||||
emb_interface_dropdown = ctk.CTkOptionMenu(
|
||||
self.embeddings_config_tab,
|
||||
values=emb_interface_options,
|
||||
variable=self.embedding_interface_format_var,
|
||||
command=on_embedding_interface_changed,
|
||||
font=("Microsoft YaHei", 12)
|
||||
)
|
||||
emb_interface_dropdown.grid(row=1, column=1, padx=5, pady=5, sticky="nsew")
|
||||
|
||||
Reference in New Issue
Block a user