File size: 7,891 Bytes
f3dd5d6
676dc22
f3dd5d6
 
01dc73d
f3dd5d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
676dc22
f3dd5d6
 
 
 
 
 
 
 
 
 
 
 
e3843d0
f3dd5d6
676dc22
f3dd5d6
e3843d0
f3dd5d6
 
 
 
 
 
 
e3843d0
f3dd5d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e3843d0
f3dd5d6
 
 
 
 
 
 
 
 
 
 
e3843d0
f3dd5d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bb303c8
f3dd5d6
bb303c8
f3dd5d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
01dc73d
f3dd5d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
01dc73d
f3dd5d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
01dc73d
f3dd5d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
01dc73d
f3dd5d6
 
 
 
 
 
 
 
 
 
 
 
 
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
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


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, f"\n{result}\n"
	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"]:
		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"
	
	if target_language in ["Deutsch", "English", "Français", "Русский язык", "中文"]:
		result = get_translaton(text, gemini_key, target_language)
		yield result
	else:
		yield "not implemented yet"


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]
	)

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

		with gr.Row():
			with gr.Column(scale=1):
				prof_language_seletor = gr.Dropdown(["DE", "EN", "FR", "RU", "ZH"], label="Prof's Language", value="EN")
				learn_language_seletor = gr.Dropdown(["DE", "EN", "FR", "RU", "ZH"], label="Language to Learn", value="EN")
				style_seletor = gr.Dropdown(["General", "Paper", "News", "Narrative", "Poem", "Philosophy"], 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
	)

	with gr.Tab("Translation"):
		gr.Markdown("### Configure Translation Settings")
		with gr.Row():
			with gr.Column(scale=1):
				target_language_selector = gr.Dropdown(
					["Deutsch", "English", "Français", "Русский язык", "中文"],
					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)