import re
from tkinter import *
from tkinter.ttk import *
from typing import Dict
import time
from datetime import datetime
import difflib
import numpy as np
# 手动粘贴版
current_out_text = ''
current_in_text = ""
title_ui_text = ""
current_in_out_flag = "in"
class WinGUI(Tk):
widget_dic: Dict[str, Widget] = {}
def __init__(self):
super().__init__()
self.__win()
self.widget_dic["tk_text_input_text"] = self.__tk_text_input_text(self)
self.widget_dic["tk_button_input_button"] = self.__tk_button_input_button(self)
global current_in_out_flag
global current_out_text
if current_in_out_flag == "out":
self.widget_dic["tk_text_input_text"].insert(END, current_out_text)
def __win(self):
self.title(title_ui_text)
# 设置窗口大小、居中
width = 378
height = 292
screenwidth = self.winfo_screenwidth()
screenheight = self.winfo_screenheight()
geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
self.geometry(geometry)
self.resizable(width=False, height=False)
# 自动隐藏滚动条
def scrollbar_autohide(self, bar, widget):
self.__scrollbar_hide(bar, widget)
widget.bind("<Enter>", lambda e: self.__scrollbar_show(bar, widget))
bar.bind("<Enter>", lambda e: self.__scrollbar_show(bar, widget))
widget.bind("<Leave>", lambda e: self.__scrollbar_hide(bar, widget))
bar.bind("<Leave>", lambda e: self.__scrollbar_hide(bar, widget))
def __scrollbar_show(self, bar, widget):
bar.lift(widget)
def __scrollbar_hide(self, bar, widget):
bar.lower(widget)
def __tk_text_input_text(self, parent):
text = Text(parent)
text.place(x=1, y=0, width=374, height=251)
return text
def __tk_button_input_button(self, parent):
btn = Button(parent, text="确定", takefocus=False, )
btn.place(x=0, y=260, width=376, height=30)
return btn
class Win(WinGUI):
def __init__(self):
super().__init__()
self.__event_bind()
def input_text_func(self, evt):
print("<Button-1>事件未处理", evt)
global current_in_out_flag
global current_in_text
if current_in_out_flag == "in":
text = self.widget_dic["tk_text_input_text"].get("0.0", END)
current_in_text = text
print(text)
self.quit()
self.destroy()
print("结束")
# sys.exit()
def __event_bind(self):
self.widget_dic["tk_button_input_button"].bind('<Button-1>', self.input_text_func)
def run_ui_input(title_text):
global title_ui_text
title_ui_text = title_text
win = Win()
win.mainloop()
def get_chat(x):
# 可以使用chatglm或者chatgpt api
run_ui_input(x)
def show_out(x):
global current_in_out_flag
global current_out_text
current_out_text = x
current_in_out_flag = "out"
run_ui_input("将此信息黏贴到chatgpt")
current_in_out_flag = "in"
demo_response = """名称:Utopia之谜
大纲:地球已被严重污染和资源耗尽,人类探索到新行星Utopia。探险队意外发现古老城市Atlantis,里面隐藏着神秘科技和外星人的实验室。人类发现Atlantis的阴谋后,拯救了这座城市并封印了外星人的实验室。
第1段:地球已面临严重的污染和资源枯竭,人类需要寻找新的地方生存。在搜索行星时,一个探险队发现了一个神秘的行星,它拥有与地球相似的环境,并被命名为“Utopia”。然而,当探险队开始在这个行星上生活时,他们发现了一个被遗忘的城市——Atlantis。
第2段:探险队进入Atlantis,惊喜地发现这座古老的城市中有许多前所未有的科技。从能够让人获得双倍力量的装置,到让人类永葆青春的药剂和能够改变命运的机器,这些科技所有人都想要拥有。然而,随着探险队逐渐深入这座城市,他们开始逐渐意识到这些神秘科技背后隐藏着一个更深不为人知的秘密。
第3段:随着探险队对Atlantis的调查加深,他们最终揭开了外星人的秘密实验室。这些外星人将人类视为敌人,开始攻击探险队。在一场殊死搏斗中,人类终于了解到Atlantis的阴谋和真相。他们成功拯救了这座城市,并封印了外星人的实验室,保存了这些珍贵的科技,最终确保了人类的未来。
摘要:人类探索到新行星Utopia,并发现了一个古老的城市Atlantis,里面隐藏着神秘的科技和外星人的秘密实验室。在一场殊死搏斗中,人类拯救了这座城市,并封印了外星人的实验室,得以保存这些珍贵的科技,最终确保了人类的未来。
指示1:探险队开始在Atlantis进行更深入的调查,最终发现外星人的真正目的。 指示2:外星人发起了另一次攻击,他们试图夺回他们的实验室。 指示3:在探险队回到Utopia开始新生活的时候,他们发现他们带回了Atlantis中的一些科技,这些科技影响了Utopia的生活,引发了新的冲突和挑战。"""
def get_api_response(content: str):
# response = openai.ChatCompletion.create(
# model='gpt-3.5-turbo',
# messages=[{
# 'role': 'system',
# 'content': 'You are a helpful and creative assistant for writing novel.'
# }, {
# 'role': 'user',
# 'content': content,
# }],
# temperature=0.5,
# max_tokens=max_tokens
# )
#
# return response['choices'][0]['message']['content']
# 手动输入
print("当前要输入的是:", content)
show_out(content)
get_chat("chatgpt的回答是")
return current_in_text
import re
def get_content_between_a_b(a, b, text):
return re.search(f"{a}(.*?)\n{b}", text, re.DOTALL).group(1).strip()
def parse_instructions(instructions):
output = ""
for i in range(len(instructions)):
output += f"{i + 1}. {instructions[i]}\n"
return output
class Human:
def __init__(self, input, memory):
self.input = input
if memory:
self.memory = memory
else:
self.memory = self.input['输出记忆']
self.output = {}
def prepare_input(self):
previous_paragraph = self.input["输入段"]
writer_new_paragraph = self.input["输出段"]
memory = self.input["输出记忆"]
user_edited_plan = self.input["输出指示"]
input_text = f"""
现在想象一下,你是一个小说家,在ChatGPT的帮助下写一本中文小说。你会得到一个先前写好的段落(由你写),和一个由你的ChatGPT助手写的段落,一个由你的ChatGPT助手保持的主要故事情节的总结,以及一个由你的ChatGPT助手提出的下一步写作计划。
我需要你写:
1. 扩展段落: 将ChatGPT助手写的新段落延长到你的ChatGPT助手所写段落的两倍。
2. 选定的计划: 复制您的ChatGPT助手提出的计划。
3. 修订的计划: 将选定的计划修改为下一段的纲要。
以前写的段落:
{previous_paragraph}。
由你的ChatGPT助手维护的主要故事情节的摘要:
{memory}
您的ChatGPT助手写的新段落:
{writer_new_paragraph}
由您的ChatGPT助手提出的下一步的写作计划:
{user_edited_plan}
现在开始写,严格按照下面的输出格式来组织你的输出,所有输出仍然保持是中文:
扩展段落:
<输出段落的字符串>,大约40-50句话。
选定的计划:
<在此复制计划>。
修改后的计划:
<修改后的计划字符串>,保持简短,大约5-7句话。
非常重要:
记住,你是在写一本小说。像小说家一样写作,在写下一段的计划时不要走得太快。在选择和扩展计划时,要考虑计划如何对普通读者具有吸引力。记住要遵循长度限制! 记住,这一章将包含10多段,而小说将包含100多章。而下一段将是第二章的第二段。你需要为未来的故事留出空间。
"""
return input_text
def parse_plan(self, response):
plan = get_content_between_a_b('选定的计划:', '理由:', response)
return plan
@staticmethod
def parse_instructions(instructions):
output = ""
for i in range(len(instructions)):
output += f"{i + 1}. {instructions[i]}\n"
return output
def select_plan(self, response_file):
previous_paragraph = self.input["输入段"]
writer_new_paragraph = self.input["输出段"]
memory = self.input["输出记忆"]
previous_plans = self.input["输出指示"]
prompt = f"""
现在想象一下,你是一个帮助小说家做决定的助手。你将得到一个以前写的段落和一个由ChatGPT写作助理写的段落,一个由ChatGPT助理保持的主要故事情节的摘要,以及接下来要写的三个不同的可能计划。
我需要你
选择由ChatGPT助手提出的最有趣和最合适的计划。
以前写的段落:
{previous_paragraph}
由你的ChatGPT助手维护的主要故事情节的摘要:
{memory}
您的ChatGPT助手写的新段落:
{writer_new_paragraph}
由您的ChatGPT助手提出的下一步写什么的三个计划:
{parse_instructions(previous_plans)}。
现在开始选择,严格按照下面的输出格式来组织你的输出:
选定的计划:
<在此复制所选计划>。
理由:
<解释你为什么选择这个计划>。
"""
print(prompt + '\n' + '\n')
response = get_api_response(prompt)
plan = self.parse_plan(response)
while plan == None:
response = get_api_response(prompt)
plan = self.parse_plan(response)
if response_file:
with open(response_file, 'a', encoding='utf-8') as f:
f.write(f"这是选定的计划:\n{response}\n\n")
return plan
def parse_output(self, text):
try:
if text.splitlines()[0].startswith('扩展段落'):
new_paragraph = get_content_between_a_b(
'扩展段落:', '选定的计划', text)
else:
new_paragraph = text.splitlines()[0]
lines = text.splitlines()
if lines[-1] != '\n' and lines[-1].startswith('修改后的计划:'):
revised_plan = lines[-1][len("修改后的计划:"):]
elif lines[-1] != '\n':
revised_plan = lines[-1]
output = {
"输出段": new_paragraph,
# "selected_plan": selected_plan,
"输出指示": revised_plan,
# "memory":self.input["output_memory"]
}
return output
except:
return None
def step(self, response_file=None):
prompt = self.prepare_input()
print(prompt + '\n' + '\n')
response = get_api_response(prompt)
self.output = self.parse_output(response)
while self.output == None:
response = get_api_response(prompt)
self.output = self.parse_output(response)
if response_file:
with open(response_file, 'a', encoding='utf-8') as f:
f.write(f"人的输出在这:\n{response}\n\n")
import random
class RecurrentGPT:
def __init__(self, input, short_memory, long_memory, memory_index, ):
self.input = input
self.short_memory = short_memory
self.long_memory = long_memory
if self.long_memory and not memory_index:
self.memory_index = self.long_memory
self.output = {}
def prepare_input(self, new_character_prob=0.1, top_k=2):
input_paragraph = self.input["输出段"]
input_instruction = self.input["输出指示"]
# 计算输入指示和长期记忆的相似度
memory_scores = [difflib.SequenceMatcher(None, input_instruction, i).quick_ratio() for i in self.long_memory]
# top_k_idx = torch.topk(torch.Tensor(memory_scores), k=top_k)[1]
top_k_idx = np.argsort(memory_scores)[::-1][:top_k]
top_k_memory = [self.long_memory[idx] for idx in top_k_idx]
# combine the top 3 paragraphs
input_long_term_memory = '\n'.join(
[f"相关段落 {i + 1} :" + selected_memory for i, selected_memory in enumerate(top_k_memory)])
# randomly decide if a new character should be introduced
if random.random() < new_character_prob:
new_character_prompt = f"如果它是合理的,你可以在输出段落中引入一个新的字符,并将其添加到记忆中。"
else:
new_character_prompt = ""
input_text = f"""
我需要你帮我写一部小说。现在我给你一个400字的记忆(一个简短的总结),你应该用它来存储已经写好的关键内容,这样你就可以记录很长的上下文。每一次,我都会给你当前的记忆(以前的故事的简要总结。你应该用它来存储所写内容的关键内容,这样你就能记下很长的上下文),之前写的段落,以及下一段要写的内容的指示。
我需要你来写:
1. 输出段落:小说的下一个段落。输出段应包含约20句话,并应遵循输入指示。
2. 输出记忆: 更新后的记忆。你应该首先解释输入记忆中的哪些句子不再需要,为什么,然后解释需要添加到记忆中的内容,为什么。之后,你应该写出更新的记忆。除了你之前认为应该删除或添加的部分,更新后的记忆应该与输入的记忆相似。更新后的记忆应该只存储关键信息。更新后的记忆不应该超过20个句子!
3. 输出指示:接下来要写什么的指示(在你写完之后)。你应该输出3个不同的指示,每个指示都是故事的一个可能的有趣的延续。每个输出指示应该包含大约5个句子
下面是输入的内容:
输入记忆:
{self.short_memory}
输入段落:
{input_paragraph}
输入指示:
{input_instruction}
输入相关段落:
{input_long_term_memory}
现在开始写,严格按照下面的输出格式来组织你的输出:
输出段:
<输出段落的字符串>,大约20句话。
输出记忆:
<输出记忆的字符串>
理由:
<解释如何更新的记忆的字符串>
更新的记忆:
<更新的记忆的字符串>,大约10到20句话
输出指示:
指示1:<指示1的内容>,大约5句话
指示2:<指示2的内容>,大约5句话
指示3:<指示3的内容>,大约5个句子
非常重要:更新的记忆应该只存储关键信息。
输出的字段必须包括:(输出段、输出记忆:、理由:、更新的记忆:、输出指示:、 指示1:、指示2:、指示3:)
最后,请记住,你是在写一本小说。像小说家一样写作,在写下一段的输出指示时,不要走得太快。记住,这一章将包含10多段,而小说将包含100多章。而这仅仅是个开始。就要写一些接下来会发生的有趣的职员。另外,在写输出说明时,要考虑什么情节能吸引普通读者。
你应该首先解释输入记忆中的哪些句子不再需要了,为什么,然后解释需要添加到记忆中的内容,为什么。之后,你开始重写输入记忆,得到更新的记忆。
{new_character_prompt}"""
return input_text
def parse_output(self, output):
try:
output_paragraph = get_content_between_a_b(
'输出段:', '输出记忆', output)
try:
output_memory_updated = get_content_between_a_b(
'更新的记忆:', '输出指示:', output)
except:
output_memory_updated = get_content_between_a_b(
'记忆:', '输出指示:', output)
self.short_memory = output_memory_updated
ins_1 = re.search("指示1:(.+)指示2", output, re.DOTALL).group(1)
ins_2 = re.search("指示2:(.+)指示3", output, re.DOTALL).group(1)
# lines = output.splitlines()
# # content of Instruction 3 may be in the same line with I3 or in the next line
# if lines[-1] != '\n' and lines[-1].startswith('指示2'):
# ins_3 = lines[-1][len("指示2:"):]
# elif lines[-1] != '\n':
# ins_3 = lines[-1]
ins_3 = re.search("指示3:(.+)\n", output, re.DOTALL).group(1)
output_instructions = [ins_1, ins_2, ins_3]
assert len(output_instructions) == 3
output = {
"输入段": self.input["输出段"],
"输出记忆": output_memory_updated, # feed to human
"输出段": output_paragraph,
"输出指示": [instruction.strip() for instruction in output_instructions]
}
return output
except:
return None
def step(self, response_file=None):
prompt = self.prepare_input()
print(prompt + '\n' + '\n')
response = get_api_response(prompt)
self.output = self.parse_output(response)
while self.output == None:
response = get_api_response(prompt)
self.output = self.parse_output(response)
if response_file:
with open(response_file, 'a', encoding='utf-8') as f:
f.write(f"作者的输出在这:\n{response}\n\n")
self.long_memory.append(self.input["输出段"])
# self.memory_index = self.embedder.encode(
# self.long_memory, convert_to_tensor=True)
if __name__ == '__main__':
run_ui_input("请输入小说类型可以自己咨询chatgpt")
typer = current_in_text
run_ui_input("请输入小说内容基本描述可以自己咨询chatgpt")
topic = current_in_text
init_prompt= f"""请写一部关于{topic}的{typer}小说,大约有50个
章节。准确地遵循以下格式:
以小说的名称开始。
接下来,写出第一章的提纲。大纲应描述小说的背景和开头。
根据你的提纲写出前三段,并说明小说的内容。
用小说的风格来写,慢慢地设置场景。
写一个总结,抓住这三段的关键信息。
最后,写出三个不同的指示,说明接下来要写什么,每个指示包含大约五句话。每个指示都应该提出一个可能的、有趣的故事的延续。
输出格式应遵循这些准则:
名字: <小说的名称>大纲: <第一章的大纲>。
第1段:<第1段的内容>。
第2段:<第2段的内容> 第3段:<第3段的内容>。
摘要: <摘要的内容>。
指示1:<指示1的内容>。
指示2:<指示2的内容>。
指示3:<指示3的内容>。
确保准确无误,严格遵守输出格式。
"""
demo_response= get_api_response(init_prompt)
with open("responses.txt", 'a', encoding='utf-8') as f:
f.write(f"初始输出:\n{demo_response}\n\n")
paragraphs = {
"名字": "",
"大纲": "",
"第1段": "",
"第2段": "",
"第3段": "",
"摘要": "",
"指示1": "",
"指示2": "",
"指示3": ""
}
# paragraphs['名字'] = get_content_between_a_b('名字:', '大纲', demo_response.replace("\n"))
paragraphs['名字'] = demo_response.split("\n\n")[0][3:]
paragraphs['第1段'] = get_content_between_a_b('第1段:', '第2段:', demo_response)
paragraphs['第1段'] = get_content_between_a_b('第2段:', '第3段:', demo_response)
paragraphs['第1段'] = get_content_between_a_b('第3段:', '摘要', demo_response)
paragraphs['摘要'] = get_content_between_a_b('第3段:', '指示1', demo_response)
paragraphs['指示1'] = re.compile("指示2:(.+)指示3").findall(demo_response)
paragraphs['指示2'] =re.compile("指示3:(.+)").findall(demo_response)
lines = demo_response.splitlines()
# content of Instruction 3 may be in the same line with I3 or in the next line
if lines[-1] != '\n' and lines[-1].startswith('指示3'):
paragraphs['指示3'] = lines[-1][len("指示3:"):]
elif lines[-1] != '\n':
paragraphs['指示3'] = lines[-1]
# Sometimes it gives Chapter outline, sometimes it doesn't
# 特殊情况的时候
# for line in lines:
# if line.startswith('Chapter'):
# paragraphs['Outline'] = get_content_between_a_b('Outline:','Chapter',response)
# break
# if paragraphs['Outline'] == '':
# paragraphs['Outline'] = get_content_between_a_b('Outline:','Paragraph',response)
start_input_to__human = {
'输出段': paragraphs['第3段'],
'输入段': '\n'.join([paragraphs['第1段'], paragraphs['第2段']]),
'输出记忆': paragraphs['摘要'],
"输出指示": [paragraphs['指示1'], paragraphs['指示2'], paragraphs['指示3']]
}
# 相似度计算模型初始化
import difflib
query_str = "公"
str2 = "上海市公"
str3 = "上海市"
print(difflib.SequenceMatcher(None, query_str, str2).quick_ratio())
print(difflib.SequenceMatcher(None, query_str, str3).quick_ratio())
human = Human(input=start_input_to__human, memory=None)
# select plan
human.input["输出指示"] = human.select_plan("responses.txt")
print(human.input["输出指示"])
human.step("responses.txt")
start_short_memory = paragraphs['摘要']
writer_start_input = human.output
# Init writerGPT
writer = RecurrentGPT(input=writer_start_input, short_memory=start_short_memory, long_memory=[
paragraphs['第1段'], paragraphs['第2段']], memory_index=None)
for i in range(2):
writer.step("responses.txt") # write new paragraph and give instructions
human.input = writer.output # update human input
human.input["输出指示"] = human.select_plan("responses.txt")
human.step("responses.txt")
writer.input = human.output # update writer input
小说:循环
梅飞雪坐在窗前,手握一卷未完成的剧本。她在思考着下一步该怎么写,需要怎样的情节来推动故事的发展。
窗外飘落着雪花,萧瑟的冷风吹得人心里也变得寒冷起来。梅飞雪也感到了困意袭来,便合上眼睛休息了一会儿。突然,她似乎听到了一个声音,一个男人的声音。那声音仿佛从剧本里传来,深沉而又低沉。
“你最好不要相信爱情,因为它只会让你伤心。”
“什么?”梅飞雪睁开眼睛,感到有些诧异,这个声音是从哪里来的?
她抬起头,发现自己不在自己的办公室里,而是在一间陌生的屋子里。房间里什么都没有,只有她自己和那个声音。“你这是怎么回事?我怎么来到这里了?”梅飞雪有些惊慌地问道。
“这是属于你的领域,你可以掌控一切,你可以编写任何你想要的故事。”
“领域?这是什么意思?”梅飞雪很不明白。
“你是一个作家,拥有无限的想象力和创造力,你可以创造出任何一个世界,任何一个人物。”那个声音解释道。
“那么,我刚才听到的那个声音是什么意思?”梅飞雪还是不明白。
“那是你刚刚写的一个情节,你是否想让它发展下去呢?”
梅飞雪犹豫了一下,最终还是点了头,她想看看这个故事会发生什么。
于是,她又坐下来,手握剧本,开始编写下一个情节。
小说:循环
李文昊是一位成功的作家,他的小说一直很受欢迎,但是他一直都没有找到想要的爱情,他心里一直很孤单。
直到有一天,他在写作过程中,遇到了一个女孩,她帮助他找回了对爱情的向往。他们相互欣赏,相互了解,最终走到了一起。但是,爱情并不像他们想象的那样美好,他们遇到了很多挑战和困难。
他们之间的感情开始变得疏远,李文昊开始怀疑他们之间的爱情是否真实。他们矛盾不断,甚至走到了分手的边缘。
李文昊最终选择了放弃,他和女孩分手了,他认为他们之间的爱情是一场美好的幻想,不可实现。
然而,几年之后,他遇到了一个女孩,与之相处的过程,让他不由自主地联想起了那个曾经的女孩,他开始意识到,爱情可能是真实存在的,也许只是他自己选择放弃了。
他决定重新开始,追回曾经失去的爱情。
李文昊又回到了刚才的故事里,他选择重新开始,对那个女孩说出了他心里最真实的想法和感受。文章来源:https://www.toymoban.com/news/detail-495754.html
故事循环往复,但是李文昊却从中学到了很多东西,他懂得了珍惜爱情,也懂得了如何处理人际关系。他不再迷失自己,他明白了,人生的道路总是充满了未知和挑战,但只有执着、勇敢和信念,才能迎接生命中的每一个关卡。文章来源地址https://www.toymoban.com/news/detail-495754.html
到了这里,关于可超长文本生成小说之循环prompt,全程ctrl+c,ctrl+c的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!