Files
AI_NovelGenerator/__pycache__/novel_generator.cpython-310.pyc
T

182 lines
18 KiB
Plaintext
Raw Normal View History

2025-01-29 20:33:20 +08:00
o
ýOœg@eã@s
ddlZddlZddlZddlmZmZmZzddlmZWney-ddl mZYnwddl
m Z ddl m
Z
mZmZddl
mZddlmZddlmZddlZddlZdd lmZdd
2025-01-29 20:33:20 +08:00
lmZdd lmZmZmZmZdd l m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)ej*ej+d
ddZ,de-de-dee-defddZ.de-de-deefddZ/de-de-de-ddfddZ0ddde-de-de-de1de-f
ddZ2Gd d!„d!eƒZ3 "dede-de-d#e-d$e-d%e-d&e1d'e1d(e-d)e4ddfd*d+„Z5id,dd-dd.dd/d0“d1dd2d3“d4d5“d6d7“d8d9“d:d;“d<d=“d>d?“d@dA“dBdC“dDdE“dFdG“Z6dHe-de1fdIdJ„Z7 0dfdKe-dLe1dMe1de-fdNdO„Z8 P "dgdQe-dRe-de-de-dSe-dLe1d(e-d'e1dTe-dUe-d)e4de-fdVdW„Z9de-de-dXe-ddfdYdZ„Z: " [dhd\e-d]e4d^e1dee-fd_d`„Z;didae-d^e1dee-fdbdc„Z<dS)jéN)ÚDictÚListÚOptional)Ú TypedDict)Ú
ChatOpenAI)Ú
StateGraphÚSTARTÚEND)ÚOpenAIEmbeddings)ÚChroma©ÚDocument)ÚSentenceTransformer)Úcosine_similarity)Ú read_fileÚappend_text_to_fileÚclear_file_contentÚsave_string_to_txt) Ú
set_promptÚcharacter_promptÚdark_lines_promptÚfinalize_setting_promptÚnovel_directory_promptÚsummary_promptÚupdate_character_state_promptÚchapter_outline_promptÚchapter_write_promptz'%(asctime)s [%(levelname)s] %(message)s)ÚlevelÚformatÚ vectorstoreÚapi_keyÚbase_urlÚtextsÚreturncCs6t||d}dd|Dƒ}tj||td}| ¡|S)
åˆå§‹åŒ–并返回一个Chromaå‘é‡åº“,将传入的文本进行嵌入并ä¿å­˜åˆ°æœ¬åœ°ç›®å½•。
如果ä¸å­˜åœ¨è¯¥ç›®å½•,会自动创建。
©Zopenai_api_keyZopenai_api_basecSóg|]}t|dqS©©Z page_contentr )Ú.0Úr*ú;c:\Users\xieli\Desktop\AI_NovelGenerator\novel_generator.pyÚ
<listcomp>3óz%init_vector_store.<locals>.<listcomp>)Z embeddingÚpersist_directory)r
r Zfrom_documentsÚVECTOR_STORE_DIRÚpersist)r r!r"Ú
embeddingsZ documentsrr*r*r+Úinit_vector_store*sþýr2cCs(tj t¡sdSt||d}tt|dS)u;读å–已存在的å‘é‡åº“。若ä¸å­˜åœ¨åˆ™è¿”回 None。Nr$)r.Zembedding_function)ÚosÚpathÚexistsr/r
r )r r!r1r*r*r+Úload_vector_store<s þ r6Ú new_chaptercCsLt||ƒ}|st d¡t|||gƒdSt|d}| |g¡| ¡dS)uf将最新章节文本æ’入到å‘é‡åº“里,用于åŽç»­æ£€ç´¢å‚考。若库ä¸å­˜åœ¨åˆ™åˆå§‹åŒ–。z6Vector store does not exist. Initializing a new one...Nr')r6ÚloggingÚinfor2r
Ú
add_documentsr0)r r!r7ÚstoreZnew_docr*r*r+Úupdate_vector_storeFs


  r<éÚqueryÚkcCsBt||ƒ}|st d¡dS|j||d}d dd|Dƒ¡}|S)uˆ
从å‘é‡åº“中检索与 query 最相关的 k æ¡æ–‡æœ¬ï¼Œæ‹¼æŽ¥åŽè¿”回。
2025-01-29 20:33:20 +08:00
è‹¥å‘é‡åº“ä¸å­˜åœ¨åˆ™è¿”回空字符串。
z0Vector store not found. Returning empty context.Ú©r?Ú
cSsg|]}|jqSr*r')r(Údr*r*r+r,\sz:get_relevant_context_from_vector_store.<locals>.<listcomp>)r6r8ÚwarningZsimilarity_searchÚjoin)r r!r>r?r;ÚdocsZcombinedr*r*r+Ú&get_relevant_context_from_vector_storeRs

rGc@sVeZdZUeed<eed<eed<eed<eed<eed<eed<eed<eed <d
S) Ú OverallStateÚtopicÚgenreÚnumber_of_chaptersÚ word_numberÚnovel_setting_baseÚcharacter_settingÚ
dark_linesÚfinal_novel_settingÚnovel_directoryN)Ú__name__Ú
__module__Ú __qualname__ÚstrÚ__annotations__Úintr*r*r*r+rHas
 rHçffffffæ?Ú llm_modelrIrJrKrLÚfilepathÚ temperaturec stj|ddt||||ddtdtfdddtd tttfffd
d } dtd tttfffd d
}
dtd tttfffdd } dtd tttfffdd } dtd tttfffdd }
ttƒ}| d| ¡| d|
¡| d| ¡| d| ¡| d|
¡| t d¡| dd¡| dd¡| dd¡| dd¡| dt
¡|  ¡}||||dœ}|  |¡}|sÇt
 d¡dS| dd¡}| dd¡}|r×|sÞt
 d¡dStj |d ¡}tj |d!¡}d"td tfd#d$„}||ƒ}||ƒ}t||ƒt||ƒt
 d%¡dS)&uÿ
使用多步æµç¨‹ï¼Œç”Ÿæˆ Novel_setting.txt 与 Novel_directory.txt å¹¶ä¿å­˜åˆ° filepath。
:param api_key: OpenAI API key
:param base_url: OpenAI API base url
:param llm_model: 所使用的 LLM 模型åç§°
:param topic: å°è¯´ä¸»é¢˜
:param genre: å°è¯´ç±»åž‹
:param number_of_chapters: 章节数
:param word_number: å•章目标字数
:param filepath: å­˜æ”¾ç”Ÿæˆæ–‡ä»¶çš„目录路径
:param temperature: ç”Ÿæˆæ¸©åº¦
Úexist_ok©Úmodelr r!r[ÚpromptÚresponse_contentcSó(t d|d¡t d|d¡dS)u@åœ¨æŽ§åˆ¶å°æ‰“å°æˆ–è®°å½•ä¸‹æ¯æ¬¡Prompt与Response,[调试]z
[Prompt >>>] rBz[Response <<<] N©r8r9©r`rar*r*r+Ú debug_logŽóz1Novel_novel_directory_generate.<locals>.debug_logÚstater#cs\tj|d|d|d|dd}ˆ |¡}|s!t d¡ddiSˆ||jƒd|j ¡iS) NrIrJrKrL©rIrJrKrLz#generate_base_setting: No response.rMr@)rrÚinvoker8rDÚcontentÚstrip©rgr`Úresponse©rer_r*r+Úgenerate_base_setting“sü

 z=Novel_novel_directory_generate.<locals>.generate_base_settingcóJtj|dd}ˆ |¡}|st d¡ddiSˆ||jƒd|j ¡iS)NrM)Ú
novel_settingz(generate_character_setting: No response.rNr@)rrrir8rDrjrkrlrnr*r+Úgenerate_character_setting¡óÿ

 zBNovel_novel_directory_generate.<locals>.generate_character_settingcrp)NrN)Zcharacter_infoz!generate_dark_lines: No response.rOr@)rrrir8rDrjrkrlrnr*r+Úgenerate_dark_lines¬rsz;Novel_novel_directory_generate.<locals>.generate_dark_linescsVtj|d|d|dd}ˆ |¡}|st d¡ddiSˆ||jƒd|j ¡iS)NrMrNrO)rMrNrOz$finalize_novel_setting: No response.rPr@)rrrir8rDrjrkrlrnr*r+Úfinalize_novel_setting·sý

 z>Novel_novel_directory_generate.<locals>.finalize_novel_settingcsPtj|d|dd}ˆ |¡}|st d¡ddiSˆ||jƒd|j ¡iS)NrPrK)rPrKz&generate_novel_directory: No response.rQr@)rrrir8rDrjrkrlrnr*r+Úgenerate_novel_directoryÄsþ

 z@Novel_novel_directory_generate.<locals>.generate_novel_directoryrorrrtrurvrhuGNovel_novel_directory_generate: invoke() 结果为空,生æˆå¤±è´¥ã€‚NrPr@rQu@生æˆå¤±è´¥ï¼šç¼ºå°‘ final_novel_setting 或 novel_directory。zNovel_setting.txtzNovel_directory.txtÚtxtcSs| dd¡ dd¡S)#r@Ú*)Úreplace)rwr*r*r+Ú
clean_textùsz2Novel_novel_directory_generate.<locals>.clean_textz4Novel settings and directory generated successfully.)r3ÚmakedirsrrUrHrrZadd_nodeZadd_edgerr Úcompilerir8rDÚgetr4rErr9)r r!rYrIrJrKrLrZr[rorrrtrurvZgraphÚappZ input_paramsÚresultrPZfinal_novel_directoryZ filename_setZfilename_novel_directoryr{Zfinal_novel_setting_cleanedZfinal_novel_directory_cleanedr*rnr+ÚNovel_novel_directory_generatels`ü  

          ü

  


rué›¶uâ—‹u〇u一éu二u三éuå››éu五éuå…­éu七éuå…«éuä¹é uåé
u百éduåƒièu万i'Ú chinese_strcCsnd}d}d}t|ƒD]&}|tvr/t|}|dkr(||kr|}q
|||7}d}q
|||}q
q
||7}|S)u\
åªèƒ½å¤„ç†åˆ°ä¸‡(10000)以内的中文数字,正常å°è¯´ç« èŠ‚åº”è¯¥å¤Ÿç”¨äº†
rr)ÚreversedÚCHINESE_NUM_MAP)ÚtotalZ current_unitZtmp_valÚcharÚvalr*r*r+Úchinese_to_arabic
s  rÚnovel_directory_textÚ novel_numberÚ
range_sizecCs| ¡}gd¢}i}|D]A}| ¡}|sq d}|D]0}tj||tjd} | rI|  d¡}
|  d¡ ¡} t d|
¡r=t|
ƒ} nt|
ƒ} | || <d}nq|rMq q g}
t||||dƒD]%}||vr€||krs|
2025-01-29 20:33:20 +08:00
  d|d ||¡q[|
  d
|d ||¡q[|
rˆd  
|
¡Sd S)
从å°è¯´ç›®å½•文本中,æå–指定章节(以åŠå‰åŽå‡ ç« ï¼‰çš„目录信æ¯ã€‚
range_size=1,表示获å–当å‰ç« èŠ‚ã€å‰ä¸€ç« å’ŒåŽä¸€ç« çš„目录信æ¯(若存在)。
支æŒå¤šç§å¸¸è§çš„章节格å¼ã€‚
)u#^第\s*([\d]+)\s*ç« [::]?\s*(.*)$uQ^第\s*([零○〇一二三四五六七八ä¹å百åƒä¸‡]+)\s*ç« [::]?\s*(.*)$u"^Chapter\s+(\d+)\s*[::]?\s*(.*)$u^Ch\s+(\d+)\s*[::]?\s*(.*)$u#^第\s*([\d]+)\s*节[::]?\s*(.*)$u#^第\s*([\d]+)\s*è¯[::]?\s*(.*)$F)Úflagsrr=u5^[零○〇一二三四五六七八ä¹å百åƒä¸‡]+$Tuã€å½“å‰ã€‘第u章:u第rBr@) Ú
splitlinesrkÚreÚmatchÚ
IGNORECASEÚgrouprrWÚrangeÚappendrE)r“r”r•ÚlinesÚpatternsZ
directory_mapÚlineZmatchedÚpatr™Zchapter_num_strZ
chapter_titleZ chapter_numZ
chapters_infoZcnumr*r*r+Ú"parse_chapter_title_from_directory+sB 
 
óÿ
r@Únovel_settingsÚnovel_novel_directoryÚ
model_nameÚ lastchapterÚ
user_guidancec s.tj|ddt||||
ddtdtfddtj |d¡} tj| ddtj | d |d
¡} tj |d ¡}
tj |d ¡}tj |d
¡}t|ƒ}t|ƒ}dtdtdtffdd }| ¡rf|||ƒ}n|}dtdtdtffdd }| ¡r€|||ƒ}n|}t||ddd}t ||dd}dtdtdtdt
dtd td!tdtffd"d#„ }|||||||| ƒ}dtdtdtd$td%t
dtd td!tdtffd&d'„ }||||||||| ƒ}|r t || ƒt |
ƒt ||
ƒt |ƒt ||ƒt |ƒt ||ƒt
|||ƒt d(|d)¡|St d(|d*¡|S)+uN
多步æµç¨‹:
1) æ›´æ–°/创建全局摘è¦
2) æ›´æ–°/生æˆè§’è‰²çŠ¶æ€æ–‡æ¡£
3) å‘釿£€ç´¢èŽ·å–往期上下文
4) 从Novel_directory.txt中获å–当å‰(å’Œå‰åŽå‡ ç« )的目录信æ¯
5) 大纲 -> 正文(å¯ç»“åˆç”¨æˆ·ç»™å‡ºçš„é¢å¤–指导)
6) 写入 chapter_{novel_number}.txt, 更新 last_chapter.txt
7) æ›´æ–°å‘é‡åº“
2025-01-29 20:33:20 +08:00
:param novel_settings: 最终的作å“设定(字符串)
:param novel_novel_directory: å°è¯´ç›®å½•ä¿¡æ¯
:param api_key: OpenAI API Key
:param base_url: OpenAI Base URL
:param model_name: LLM 模型åç§°
:param novel_number: 当å‰è¦ç”Ÿæˆçš„章节å·
:param filepath: 文件存放的目录
:param word_number: å•章目标字数
:param lastchapter: 上一章内容(若为空字符串,表示无上一章)
:param user_guidance: 用户对当å‰ç« èŠ‚çš„é¢å¤–指导或想法
:param temperature: ç”Ÿæˆæ¸©åº¦
:return: 本章生æˆçš„æ­£æ–‡å†…容
Tr\r^r`racSrb)uYåœ¨æŽ§åˆ¶å°æ‰“å°æˆ–è®°å½•ä¸‹æ¯æ¬¡çš„ Prompt 与 Response,便于观察生æˆè¿‡ç¨‹ã€‚z
2025-01-29 20:33:20 +08:00
[Prompt >>>]
rBz[Response <<<]
Nrcrdr*r*r+re¥rfz.generate_chapter_with_state.<locals>.debug_logZchaptersZchapter_z.txtzlast_chapter.txtzcharacter_state.txtzglobal_summary.txtÚ chapter_textÚ old_summaryr#có@tj||d}ˆ |¡}|st d¡|Sˆ||jƒ|j ¡S)N)Úglobal_summaryz#update_global_summary: No response.)rrrir8rDrjrk)r`rmrnr*r+Úupdate_global_summary·óþ

 
z:generate_chapter_with_state.<locals>.update_global_summaryÚ old_statec)N)z$update_character_state: No response.)rrrir8rDrjrk)r`rmrnr*r+Úupdate_character_stateÉr­z;generate_chapter_with_state.<locals>.update_character_stateu 回顾剧情r=rAr‚)r•rqÚ
char_stater«Úchap_numÚ
extra_contextÚdirectory_hintÚ
user_guidec s\td|d|j||d|||d}ˆ |¡}|s#t d¡dSˆ||jƒ|j ¡S)uY
将目录æç¤ºä»¥åŠç”¨æˆ·é¢å¤–指导内容一起放入 Prompt 中。
õ
ã€ç›®å½•å‚考】
õ
ã€ç”¨æˆ·æŒ‡å¯¼ã€‘
õ
ã€åކå²ä¸Šä¸‹æ–‡ã€‘
)rqÚcharacter_stater«r”zoutline_chapter: No response.r@)rrrir8rDrjrk) rqr´Zoutline_promptrmrnr*r+Úoutline_chapterãs*ÿÿþþ
ø

 
z4generate_chapter_with_state.<locals>.outline_chapterÚoutlineÚwnumc
s^td|d|j||d||||d}ˆ |¡} | s$t d¡dSˆ|| jƒ| j ¡S)Nrµ)rqr¸Zchapter_outlinerLzwrite_chapter: No response.r@)rrrir8rDrjrk)
rqr´Zwriting_promptrmrnr*r+Ú
write_chapters, ÿÿþþ
÷

 
z2generate_chapter_with_state.<locals>.write_chapterzChapter z generated successfully.z generation failed.)r3r|rrUr4rErrkrGrWrrr<r8r9rD)r r!r”rZrLr[Z chapters_dirZ chapter_fileZlastchapter_fileÚcharacter_state_fileÚglobal_summary_fileZold_char_stateZold_global_summaryr¬Znew_global_summaryr¯Znew_char_stateZrelevant_contextZthis_and_related_chaptersr¹Z chap_outliner¼Zchapter_contentr*rnr+Úgenerate_chapter_with_statev%ü  ÿÿþýüûúùøþÿþýüûúùø ÷ø



 þr¿Ú file_pathcCtj |¡st d|¡dSt|ƒ}| ¡st d¡dSt|ƒ}t||ƒ}|s7t  d¡t
|||ƒdSdd|Dƒ}|  |¡|  ¡t  d¡dS)
将用户选定的文本文件导入到å‘é‡åº“,以便在写作时检索。
å¯ä»¥åœ¨UI中æä¾›æŒ‰é’®æ¥è°ƒç”¨æ­¤å‡½æ•°ã€‚
u知识库文件ä¸å­˜åœ¨: Nu知识库文件内容为空。zKVector store does not exist. Initializing a new one for knowledge import...cSr%r&r )r(Úpr*r*r+r,dr-z)import_knowledge_file.<locals>.<listcomp>u-知识库文件已æˆåŠŸå¯¼å…¥è‡³å‘é‡åº“。)
r3r4r5r8rDrrkÚadvanced_split_contentr6r9r2r:r0)r r!rjZ
paragraphsr;rFr*r*r+Úimport_knowledge_fileHs"