File size: 6,276 Bytes
f6bff5d
ebb3019
 
13a1b41
 
ebb3019
 
13a1b41
ebb3019
 
 
 
 
 
13a1b41
 
 
ebb3019
 
 
 
 
13a1b41
 
 
ebb3019
13a1b41
 
ebb3019
 
 
 
 
 
 
 
13a1b41
ebb3019
 
13a1b41
ebb3019
 
13a1b41
 
ebb3019
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13a1b41
ebb3019
 
 
 
 
 
 
 
 
 
 
 
13a1b41
2a9478d
 
ebb3019
 
 
 
 
 
 
13a1b41
ebb3019
 
 
 
13a1b41
ebb3019
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13a1b41
 
 
 
 
 
 
 
 
ebb3019
 
 
 
13a1b41
ebb3019
 
 
 
 
13a1b41
 
 
ebb3019
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2a9478d
f6bff5d
 
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import gradio as gr
from vocab import get_sources, get_words_from_source, get_word_info
from sentences import get_sentences_by_word, get_words_with_sentences, save_sentence
from ai_sentence import generate_sentence, MODEL_LIST


# 查詢例句模式 - 處理函數
def fetch_sentence(word, source, use_ai, model_name):
    status_log = []
    result_display = ""

    # 1️⃣ 檢查單字是否存在於該單字庫
    words_data = get_words_from_source(source)
    valid_words = {w['word'] for w in words_data}
    if word not in valid_words:
        return f"<p style='color:red;'>❌ 單字 {word} 不在 {source} 單字庫中</p>", "檢查失敗"

    # 2️⃣ 查詢單字音標(用於顯示 & AI 生成時存入資料庫)
    word_info = get_word_info(source, word)
    phonetic = word_info['phonetic'] if word_info else "無"

    # 3️⃣ 查詢句庫
    sentence_records = get_sentences_by_word(word)

    if not use_ai:
        # 不使用 AI,只查句庫
        for record in sentence_records:
            _, phonetic, sentence, src, model = record
            result_display += f"""
            <div style="margin-bottom: 10px; padding: 8px; border-left: 4px solid #4CAF50; background-color: #f9f9f9;">
                <strong>單字:</strong> {word} <br>
                <strong>音標:</strong> {phonetic or '無'} <br>
                <strong>句子:</strong> {sentence} <br>
                <strong>來源:</strong> {src} {f'({model})' if model else ''}
            </div>
            """
        if not sentence_records:
            result_display = f"<p style='color:red;'>❌ 查無例句:{word}</p>"

    else:
        # 使用 AI 生成
        status_log.append(f"🤖 使用 AI 模型 {model_name} 生成句子中...")
        try:
            sentence = generate_sentence(word, model_name)
            result_display = f"""
            <div style="margin-bottom: 10px; padding: 8px; border-left: 4px solid #2196F3; background-color: #f9f9f9;">
                <strong>單字:</strong> {word} <br>
                <strong>音標:</strong> {phonetic} <br>
                <strong>句子:</strong> {sentence} <br>
                <strong>來源:</strong> AI 生成 ({model_name})
            </div>
            """

            # 若句庫沒這個單字,才存入資料庫
            if not sentence_records:
                save_sentence(word, phonetic, sentence, 'ai', model_name)
                status_log.append(f"✅ AI 生成句子已儲存:{word} ({model_name})")
            else:
                status_log.append(f"🔄 AI 生成句子,但句庫已有紀錄,未覆蓋:{word}")

        except Exception as e:
            result_display = f"<p style='color:red;'>❌ AI 生成句子失敗:{str(e)}</p>"
            status_log.append(f"❌ 生成失敗:{str(e)}")

    return result_display, "\n".join(status_log)


# 模式切換邏輯
def toggle_mode(mode):
    return {
        "query": (gr.update(visible=True), gr.update(visible=False)),
        "random": (gr.update(visible=False), gr.update(visible=True)),
    }[mode]


with gr.Blocks() as demo:
    gr.Markdown(
        """
        # 📖 VocabLine 單字例句查詢 & 生成平台

        ## 📝 專案簡介
        VocabLine 是一個單字例句工具,提供查詢句庫例句、AI 生成句子功能。  
        可作為 LINE 單字推播、自學工具、英文教學輔助等用途。

        ## ⚙️ 主要功能
        - 支援從多個單字庫選擇。
        - 可查詢單字句庫例句或使用 GPT AI 生成例句。
        - 隨機抽取單字,生成例句。

        ## 🗂️ 資料來源
        - 單字庫:common3000 等
        - 句庫來源:Tatoeba 例句、AI 生成句子(GPT)

        ## 🛠️ 技術架構
        - Gradio Blocks 前端介面
        - Hugging Face Transformers 語言模型(GPT)
        - SQLite 句庫

        ## 👨‍💻 開發者資訊
        - 開發者:余彦志 (大宇 ian)
        - 信箱:[email protected]
        - GitHub:[https://github.com/dayuian](https://github.com/dayuian)

        ## 📲 LINE 推播(未來開發)
        - 本工具將結合 LINE,透過 Make.com 每日推播單字和例句,敬請期待!
        """
    )

    # 模式選擇
    mode_radio = gr.Radio(
        ["query", "random"],
        label="選擇模式",
        choices=["query", "random"],
        value="query",
        interactive=True,
        info="query:單字查詢模式 | random:隨機抽單字模式"
    )

    # 查詢模式區塊
    with gr.Group(visible=True) as query_mode:
        source_dropdown_query = gr.Dropdown(choices=get_sources(), value="common3000", label="選擇單字庫")
        word_input = gr.Textbox(label="輸入單字")
        use_ai_checkbox = gr.Checkbox(label="使用 AI 生成句子")
        model_dropdown = gr.Dropdown(choices=MODEL_LIST, value=MODEL_LIST[0], label="選擇 AI 模型", visible=False)
        query_result = gr.HTML()
        query_status = gr.Textbox()
        query_button = gr.Button("查詢例句")

    # 隨機抽單字模式區塊
    with gr.Group(visible=False) as random_mode:
        source_dropdown_random = gr.Dropdown(choices=get_sources(), value="common3000", label="選擇單字庫")
        num_input = gr.Number(value=5, label="抽幾個單字")

        random_result_output = gr.HTML()
        random_status_output = gr.Textbox()
        submit_btn = gr.Button("生成例句")

    # 查詢模式互動
    query_button.click(
        fetch_sentence,
        inputs=[word_input, source_dropdown_query, use_ai_checkbox, model_dropdown],
        outputs=[query_result, query_status],
    )

    # 隨機抽單字模式互動
    submit_btn.click(
        fn=get_words_with_sentences,
        inputs=[source_dropdown_random, num_input],
        outputs=[random_result_output, random_status_output]
    )

    # 模式切換邏輯
    mode_radio.change(
        toggle_mode,
        inputs=[mode_radio],
        outputs=[query_mode, random_mode],
    )

    # 切換 AI 模型下拉選單可見性
    use_ai_checkbox.change(
        lambda use_ai: gr.update(visible=use_ai),
        inputs=[use_ai_checkbox],
        outputs=[model_dropdown]
    )

demo.launch()