File size: 5,492 Bytes
217acfe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import time
from core.parser_utils import parse_chapters
from core.summary_novel import summary_draft, summary_plot, summary_chapters
from config import MAX_NOVEL_SUMMARY_LENGTH, MAX_THREAD_NUM, ENABLE_ONLINE_DEMO

def batch_yield(generators, max_co_num=5, ret=[]):
    results = [None] * len(generators)
    yields = [None] * len(generators)
    finished = [False] * len(generators)

    while True:
        co_num = 0
        for i, gen in enumerate(generators):
            if finished[i]:
                continue

            try:
                co_num += 1
                yield_value = next(gen)
                yields[i] = yield_value
            except StopIteration as e:
                results[i] = e.value
                finished[i] = True
            
            if co_num >= max_co_num:
                    break
        
        if all(finished):
            break

        yield yields

    ret.clear()
    ret.extend(results)
    return ret

def process_novel(content, novel_name, model, sub_model, max_novel_summary_length, max_thread_num):
    if ENABLE_ONLINE_DEMO:
        if max_novel_summary_length > MAX_NOVEL_SUMMARY_LENGTH:
            raise Exception("在线Demo模型下,最大小说长度不能超过" + str(MAX_NOVEL_SUMMARY_LENGTH) + "个字符!")
        if max_thread_num > MAX_THREAD_NUM:
            raise Exception("在线Demo模型下,最大线程数不能超过" + str(MAX_THREAD_NUM) + "!")

    if len(content) > max_novel_summary_length:
        content = content[:max_novel_summary_length]
        yield {"progress_msg": f"小说长度超出最大处理长度,已截断,只处理前{max_novel_summary_length}个字符。"}
        time.sleep(1)

    # Parse chapters
    yield {"progress_msg": "正在解析章节..."}

    chapter_titles, chapter_contents = parse_chapters(content)

    yield {"progress_msg": "解析出章节数:" + str(len(chapter_titles))}

    if len(chapter_titles) == 0:
        raise Exception("解析出章节数为0!!!")

    # Process draft summaries
    yield {"progress_msg": "正在生成剧情摘要..."}
    dw_list = []
    gens = [summary_draft(model, sub_model, ' '.join(title), content) for title, content in zip(chapter_titles, chapter_contents)]
    for yields in batch_yield(gens, ret=dw_list, max_co_num=max_thread_num):
        chars_num = sum([e['chars_num'] for e in yields if e is not None])
        current_cost = sum([e['current_cost'] for e in yields if e is not None])
        currency_symbol = next(e['currency_symbol'] for e in yields if e is not None)
        model_text = next(e['model'] for e in yields if e is not None)
        yield {"progress_msg": f"正在生成剧情摘要 进度:{sum([1 for e in yields if e is not None])} / {len(yields)} 模型:{model_text} 已生成字符:{chars_num} 已花费:{current_cost:.4f}{currency_symbol}"}

    # Process plot summaries
    yield {"progress_msg": "正在生成章节大纲..."}
    cw_list = []
    gens = [summary_plot(model, sub_model, ' '.join(title), dw.x) for title, dw in zip(chapter_titles, dw_list)]
    for yields in batch_yield(gens, ret=cw_list, max_co_num=max_thread_num):
        chars_num = sum([e['chars_num'] for e in yields if e is not None])
        current_cost = sum([e['current_cost'] for e in yields if e is not None])
        currency_symbol = next(e['currency_symbol'] for e in yields if e is not None)
        model_text = next(e['model'] for e in yields if e is not None)
        yield {"progress_msg": f"正在生成章节大纲 进度:{sum([1 for e in yields if e is not None])} / {len(yields)} 模型:{model_text} 已生成字符:{chars_num} 已花费:{current_cost:.4f}{currency_symbol}"}

    # Process chapter summaries
    yield {"progress_msg": "正在生成全书大纲..."}
    ow_list = []
    gens = [summary_chapters(model, sub_model, novel_name, chapter_titles, [cw.global_context['chapter'] for cw in cw_list])]
    for yields in batch_yield(gens, ret=ow_list, max_co_num=max_thread_num):
        chars_num = sum([e['chars_num'] for e in yields if e is not None])
        current_cost = sum([e['current_cost'] for e in yields if e is not None])
        currency_symbol = next(e['currency_symbol'] for e in yields if e is not None)
        model_text = next(e['model'] for e in yields if e is not None)
        yield {"progress_msg": f"正在生成全书大纲 模型:{model_text} 已生成字符:{chars_num} 已花费:{current_cost:.4f}{currency_symbol}"}

    # Prepare final response
    outline = ow_list[0]
    plot_data = {}
    draft_data = {}

    for title, chapter_outline, cw, dw in zip(chapter_titles, [e[1] for e in outline.xy_pairs], cw_list, dw_list):
        chapter_name = ' '.join(title)
        plot_data[chapter_name] = {
            'chunks': [('', e) for e, _ in dw.xy_pairs],
            'context': chapter_outline # 不采用cw.global_context['chapter'],因为不含章节名
        }
        draft_data[chapter_name] = {
            'chunks': dw.xy_pairs,
            'context': ''  # Draft doesn't have global context
        }

    final_response = {
        "progress_msg": "处理完成!",
        "outline": {
            "chunks": outline.xy_pairs,
            "context": outline.global_context['outline']
        },
        "plot": plot_data,
        "draft": draft_data
    }

    yield final_response