File size: 12,128 Bytes
28d86ed
aeea3ef
28d86ed
 
aeea3ef
28d86ed
a2fcb2d
28d86ed
 
 
 
 
 
 
79a1ae4
 
428a945
79a1ae4
 
 
428a945
79a1ae4
 
 
 
28d86ed
79a1ae4
 
28d86ed
79a1ae4
28d86ed
 
aeea3ef
79a1ae4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84a1425
79a1ae4
 
 
28d86ed
 
428a945
79a1ae4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28d86ed
 
428a945
79a1ae4
428a945
 
 
 
 
 
 
 
 
 
79a1ae4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
af744f3
 
a2fcb2d
 
 
 
 
79a1ae4
a2fcb2d
 
 
 
 
 
 
 
af744f3
79a1ae4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
af744f3
 
28d86ed
79a1ae4
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
import gradio as gr
from gradio import File
from process.ocr import perform_raw_ocr, correct_text_with_ai
from process.interpretation import get_interpretation
from process.translation import get_translaton
from process.gradio_css import CUSTOM_CSS
from process.agent import AutomatedAnalysisAgent


MISTRAL_API_KEY = ""
GEMINI_API_KEY = ""


def update_api_keys(mistral_key, gemini_key):
    """
    Updates the global MISTRAL_API_KEY and GEMINI_API_KEY variables.

    Args:
            mistral_key: The Mistral API key.
            gemini_key: The Gemini API key.

    Returns:
            A string confirming that the API keys have been saved.
    """
    global MISTRAL_API_KEY, GEMINI_API_KEY

    MISTRAL_API_KEY = mistral_key
    GEMINI_API_KEY = gemini_key

    return "API keys saved"


def ocr_workflow_wrapper(file: File, mistral_key: str):
    """
    Manages the OCR workflow, processing an uploaded file to extract text.

    Args:
            file: The file object to process (image, PDF, or text).
            mistral_key: The Mistral API key for OCR processing.

    Yields:
            Status messages and the extracted text or error messages.
    """
    if not mistral_key:
        error_msg = "Error: Mistral API Key not set."
        yield error_msg, error_msg
        return
    if not file or file.name == "":
        error_msg = "Error: File/Text not found."
        yield error_msg, error_msg
        return

    try:
        result = perform_raw_ocr(file, mistral_key)
        yield result, result
    except Exception as e:
        error_msg = f"An error occurred during processing: {str(e)}"
        yield error_msg, error_msg


def ai_correct(current_text: str, mistral_key: str):
    """
    Corrects the provided text using an AI model.

    Args:
            current_text: The text to be corrected.
            mistral_key: The Mistral API key for AI correction.

    Yields:
            Status messages and the corrected text or error messages.
    """
    if not mistral_key:
        error_msg = "Error: Mistral API Key not set."
        yield error_msg, error_msg
        return
    if not current_text or current_text.strip() == "":
        error_msg = "*No text to correct. Upload a file, or paste text into 'Raw Text' box first*"
        yield error_msg, error_msg
        return

    try:
        result = correct_text_with_ai(current_text, mistral_key)
        yield result, result
    except Exception as e:
        error_msg = f"Error : {e}"
        yield error_msg, error_msg


def interpretation_workflow(
    text: str, genre: str, learn_language: str, target_language: str, gemini_key: str
):
    """
    Generates an interpretation of the text based on genre and language settings.

    Args:
            text: The text to interpret.
            genre: The genre of the text (e.g., "general", "news").
            learn_language: The language being learned.
            target_language: The language for the interpretation output.
            gemini_key: The Gemini API key for interpretation.

    Yields:
            Status messages and the generated interpretation or error messages.
    """
    if not gemini_key:
        yield "Error: Gemini api key not found."
        return
    if not text or text.strip() == "":
        yield "Error: Text is empty"
        return
    if not learn_language or not target_language:
        yield "Error: Language not selected"
        return

    if genre.lower() in ["general", "news", "philosophy"]:
        result = get_interpretation(
            genre.lower(), gemini_key, text, learn_language, target_language
        )
        yield result
    else:
        yield "not implemented yet"


def translation_workflow(text: str, target_language: str, gemini_key):
    """
    Translates the provided text to the target language.

    Args:
        text: The text to translate.
        target_language: The language to translate the text into.
        gemini_key: The Gemini API key for translation.

    Yields:
        Status messages and the translated text or error messages.
    """
    if not gemini_key:
        yield "Error: Gemini api key not found."
        return
    if not text or text.strip() == "":
        yield "Error: Text is empty"
        return
    if not target_language:
        yield "Error: Language not selected"

    existin_languages = [
        "العربية",
        "Deutsch",
        "Español",
        "English",
        "Français",
        "Italiano",
        "日本語",
        "Русский язык",
        "中文",
    ]
    if target_language in existin_languages:
        result = get_translaton(text, gemini_key, target_language)
        yield result
    else:
        yield "not implemented yet"


def agent_workflow(text: str, prof_language: str, mistral_key: str, gemini_key: str):
    if not mistral_key or not gemini_key:
        return "Error: Both Mistral and Gemini API keys are required."
    if not text or not text.strip():
        return "Error: Input text is empty."

    try:
        agent = AutomatedAnalysisAgent(mistral_key=mistral_key, gemini_key=gemini_key)
        result = agent.run(text, prof_language=prof_language)
        return result
    except Exception as e:
        return f"An error occurred in the agent workflow: {e}"


with gr.Blocks(theme=gr.themes.Monochrome(), css=CUSTOM_CSS) as demo:
    gr.Markdown(
        "# 📚 LogosAI - Intensive Reading in Any Language",
        elem_classes=["section-header"],
    )

    # --- API Key ---
    with gr.Accordion("API Configuration", open=True):
        with gr.Row():
            with gr.Column(scale=2):
                mistral_api = gr.Textbox(
                    label="Mistral API Key",
                    type="password",
                    placeholder="Enter your key",
                    info="OCR recognition & text processing",
                )
            with gr.Column(scale=2):
                gemini_api = gr.Textbox(
                    label="Gemini API Key",
                    type="password",
                    placeholder="Enter your key",
                    info="text interpretation",
                )
            with gr.Column(scale=1):
                update_keys_button = gr.Button("Save keys")

    api_key_status_output = gr.Markdown()

    update_keys_button.click(
        fn=update_api_keys,
        inputs=[mistral_api, gemini_api],
        outputs=api_key_status_output,
    )

    # --- Text Processing ---
    gr.Markdown("---")
    with gr.Tab("Text"):
        with gr.Row():
            with gr.Column(scale=1):
                gr.Markdown("### Upload documents")
                file_input = gr.File(
                    label="Upload Image/PDF/text", file_types=["image", ".pdf", ".txt"]
                )
                process_button = gr.Button(
                    "1. File Process (OCR/Read)", variant="primary"
                )
                ai_correct_button = gr.Button("2. AI Correct", variant="primary")
            with gr.Column(scale=2):
                gr.Markdown("### Processed result")
                with gr.Tabs():
                    with gr.Tab("Raw Text"):
                        text_display = gr.Textbox(
                            label="Raw Text(editable)",
                            lines=15,
                            max_lines=20,
                            show_copy_button=True,
                            value="",
                            interactive=True,
                        )
                    with gr.Tab("Formatted Text"):
                        text_markdown = gr.Markdown(
                            value="*Processed text will appear here...*\n\n",
                            label="Formatted Text",
                        )

    # Hook the ocr button to click event
    process_button.click(
        fn=ocr_workflow_wrapper,
        inputs=[file_input, mistral_api],
        outputs=[text_display, text_markdown],
    )

    # AI correction button to click event
    ai_correct_button.click(
        fn=ai_correct,
        inputs=[text_display, mistral_api],
        outputs=[text_display, text_markdown],
    )

    # --- Agent ---
    with gr.Tab("Agent"):
        gr.Markdown("### Automated Analysis")
        with gr.Row():
            with gr.Column(scale=1):
                agent_prof_language_selector = gr.Dropdown(
                    ["AR", "DE", "ES", "EN", "FR", "IT", "JA", "RU", "ZH"],
                    label="Prof's Language",
                    value="EN",
                )
                agent_run_button = gr.Button(
                    "Run Automated Analysis", variant="primary"
                )
            with gr.Column(scale=2):
                gr.Markdown("### Agent Result")
                agent_output = gr.Markdown(
                    value="*Agent analysis will appear here...*\n\n",
                    label="Agent Result",
                )

        agent_run_button.click(
            fn=agent_workflow,
            inputs=[
                text_display,
                agent_prof_language_selector,
                mistral_api,
                gemini_api,
            ],
            outputs=agent_output,
        )

    # --- Text Interpertation ---
    with gr.Tab("🎓 Interpretation"):
        gr.Markdown("### Configure Interpretation Settings")

        with gr.Row():
            with gr.Column(scale=1):
                prof_language_seletor = gr.Dropdown(
                    ["AR", "DE", "ES", "EN", "FR", "IT", "JA", "RU", "ZH"],
                    label="Prof's Language",
                    value="EN",
                )
                learn_language_seletor = gr.Dropdown(
                    ["AR", "DE", "ES", "EN", "FR", "IT", "JA", "RU", "ZH"],
                    label="Language to Learn",
                    value="EN",
                )
                style_seletor = gr.Dropdown(
                    ["General", "News", "Philosophy", "Narrative", "Poem", "Paper"],
                    label="Genre",
                )
                interpret_button = gr.Button(
                    "Generate Interpretation", variant="primary"
                )

            with gr.Column(scale=2):
                gr.Markdown("### COURSE")
                interpretation_output = gr.Markdown(
                    value="*Interpretation will appear here after processing...*\n\n",
                    label="Interpretation Result",
                    show_copy_button=True,
                )

    interpret_button.click(
        fn=interpretation_workflow,
        inputs=[
            text_display,
            style_seletor,
            learn_language_seletor,
            prof_language_seletor,
            gemini_api,
        ],
        outputs=interpretation_output,
    )

    # --- Translation ---
    with gr.Tab("Translation"):
        gr.Markdown("### Configure Translation Settings")
        with gr.Row():
            with gr.Column(scale=1):
                target_language_selector = gr.Dropdown(
                    [
                        "العربية",
                        "Deutsch",
                        "Español",
                        "English",
                        "Français",
                        "Italiano",
                        "日本語",
                        "Русский язык",
                        "中文",
                    ],
                    value="English",
                    label="Target Language",
                    interactive=True,
                )
                translation_button = gr.Button("Translate!", variant="primary")

            with gr.Column(scale=2):
                interpretation_output = gr.Markdown(
                    value="*Translation will appear here ...*\n\n",
                    label="Translation Result",
                    show_copy_button=True,
                )

    translation_button.click(
        fn=translation_workflow,
        inputs=[text_display, target_language_selector, gemini_api],
        outputs=interpretation_output,
    )


if __name__ == "__main__":
    demo.launch(mcp_server=True)