File size: 6,521 Bytes
1f1caf1
 
900fe2a
1f1caf1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
900fe2a
1f1caf1
 
 
900fe2a
 
 
1f1caf1
 
 
 
900fe2a
1f1caf1
900fe2a
 
 
 
1f1caf1
 
900fe2a
 
 
 
 
1f1caf1
 
900fe2a
 
 
 
 
1f1caf1
 
900fe2a
1f1caf1
900fe2a
 
 
 
 
1f1caf1
 
 
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Adapted from https://github.com/THUDM/ChatGLM-6B/blob/main/web_demo.py

init_history = [
    ('你讀過《故事課》嗎?',
     '''作為一個 AI 模型,我沒有「讀」過任何書籍,但我對《故事課》這本書有一定的了解。《故事課》是一本關於故事創作和 storytelling 的書籍,作者是美国作家 John D. Walsh。

這本書提供了一些有用的建議和技巧,幫助讀者如何創作出引人入勝的故事。它涵蓋了故事創作的各個方面,包括故事結構、角色塑造、情節設計和語言表達等。此外,這本書還提供了一些實用的例子和案例分析,讓讀者可以更好地理解故事創作的過程和技巧。

總的來說,《故事課》是一本對故事創作很有幫助的書籍,尤其對於那些想寫故事或想提高自己故事創作能力的人來說,這本書會是一本很有價值的參考資料。'''),
    ('《故事課》提到哪些故事公式?',
     '''《故事課》這本書提到了一些故事公式或故事結構,這些結構可以幫助創作故事。以下是其中一些常見的故事公式:

1. 起承轉合:這是最基礎的故事結構,也稱為三幕結構。故事開始,然後有了一個轉折,接著是高潮,最後有了一個結局。
2. 英雄之旅:這是一個很常見的故事結構,也被稱為綠傳或 gray area。它描述了一個英雄從平凡無奇的生活中開始,經歷了一系列挑戰和冒險,最終達成目標的故事。
3. 成長故事:這是一個關於個人成長和發展的成長故事,它通常描述了一個人物從一個脆弱或不成熟的状态開始,通過經歷挑戰和學習,最終成長和成熟的故事。
4. 反轉结局:這是一個比較特別的结局,它通常在故事的最後出現,並且會對讀者產生一種意外的冲击和影響。
5. 寓言故事:這是一種用故事來說明一個道理或概念的故事,通常包含一個寓意或象徵性的元素。

這些故事公式只是故事創作中的一部分,不同的故事可能会有不同的結構和情節,但這些公式可以作為一個起點,幫助你開始創作出一個引人入勝的故事。'''),
]

import os
import argparse
from pathlib import Path

import chatglm_cpp
import gradio as gr

os.system("wget https://huggingface.co/npc0/chatglm3-6b-int4/resolve/main/chatglm3-ggml-q4_0.bin")

DEFAULT_MODEL_PATH = Path(__file__).resolve().parent.parent / "chatglm3-ggml-q4_0.bin"

parser = argparse.ArgumentParser()
parser.add_argument("-m", "--model", default=DEFAULT_MODEL_PATH, type=Path, help="model path")
parser.add_argument("--mode", default="chat", type=str, choices=["chat", "generate"], help="inference mode")
parser.add_argument("-l", "--max_length", default=2048, type=int, help="max total length including prompt and output")
parser.add_argument("-c", "--max_context_length", default=512, type=int, help="max context length")
parser.add_argument("--top_k", default=0, type=int, help="top-k sampling")
parser.add_argument("--top_p", default=0.7, type=float, help="top-p sampling")
parser.add_argument("--temp", default=0.95, type=float, help="temperature")
parser.add_argument("--repeat_penalty", default=1.0, type=float, help="penalize repeat sequence of tokens")
parser.add_argument("-t", "--threads", default=0, type=int, help="number of threads for inference")
parser.add_argument("--plain", action="store_true", help="display in plain text without markdown support")
args = parser.parse_args()

pipeline = chatglm_cpp.Pipeline(args.model)


def postprocess(text):
    if args.plain:
        return f"<pre>{text}</pre>"
    return text


def predict(input, chatbot, max_length, top_p, temperature, history):
    chatbot.append((postprocess(input), ""))
    response = ""
    history.append(input)

    generation_kwargs = dict(
        max_length=max_length,
        max_context_length=args.max_context_length,
        do_sample=temperature > 0,
        top_k=args.top_k,
        top_p=top_p,
        temperature=temperature,
        repetition_penalty=args.repeat_penalty,
        num_threads=args.threads,
        stream=True,
    )
    generator = (
        pipeline.chat(history, **generation_kwargs)
        if args.mode == "chat"
        else pipeline.generate(input, **generation_kwargs)
    )
    for response_piece in generator:
        response += response_piece
        chatbot[-1] = (chatbot[-1][0], postprocess(response))

        yield chatbot, history

    history.append(response)
    yield chatbot, history


def reset_user_input():
    return gr.update(value="")


def reset_state():
    history = gr.State(init_history)
    return [], []


max_length = 2048
top_p = args.top_p
temperature = args.temp
with gr.Blocks() as demo:
    gr.HTML("""<h1 align="center">劇本測試</h1>""")
    with gr.Row():
        with gr.Column(scale=4):
            user_input = gr.Textbox(show_label=False, placeholder="Step1:主題設定", lines)
        with gr.Column(scale=1):
            submitBtn = gr.Button("Submit", variant="primary")
            # max_length = gr.Slider(0, 2048, value=args.max_length, step=1.0, label="Maximum Length", interactive=True)
            # top_p = gr.Slider(0, 1, value=args.top_p, step=0.01, label="Top P", interactive=True)
            # temperature = gr.Slider(0, 1, value=args.temp, step=0.01, label="Temperature", interactive=True)
            emptyBtn = gr.Button("Clear History")

    five_sample = gr.Textbox(show_label=False, placeholder="五個範例")
    expand = gr.Dropdown(["1", "2", "3", "4", "5"], label="Step2:進一步擴展的範例")
    final_sample = gr.Textbox(show_label=False, placeholder="大綱")

    history = gr.State(init_history)

    submitBtn.click(
        predict, [
            '請為『%s』選取5個公式' %user_input,
            chatbot, max_length, top_p,
            temperature, history],
        [chatbot, history], show_progress=True
    )
    submitBtn.click(reset_user_input, [], [user_input])
    submitBtn.click(reset_user_input, [], [final_sample])

    expand.select(fn=predict,
                  inputs=('現在你作為一個專業的編劇,'
                          '你需要為故事%轉寫一段故事大綱'
                          '提供一個完整的龍骨給之後的編劇用。') %expand,
                  outputs=final_sample)
    emptyBtn.click(reset_state, outputs=[chatbot, history], show_progress=True)

demo.queue().launch(share=False, inbrowser=True)