IvanMiao commited on
Commit
a2fcb2d
·
1 Parent(s): ed00853

feat: agent

Browse files
Files changed (2) hide show
  1. app.py +36 -0
  2. process/agent.py +102 -0
app.py CHANGED
@@ -4,6 +4,7 @@ from process.ocr import perform_raw_ocr, correct_text_with_ai
4
  from process.interpretation import get_interpretation
5
  from process.translation import get_translaton
6
  from process.gradio_css import CUSTOM_CSS
 
7
 
8
 
9
  MISTRAL_API_KEY = ""
@@ -144,6 +145,20 @@ def translation_workflow(text: str, target_language: str, gemini_key):
144
  yield "not implemented yet"
145
 
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  with gr.Blocks(theme=gr.themes.Monochrome(), css=CUSTOM_CSS) as demo:
148
  gr.Markdown("# 📚 LogosAI - Intensive Reading in Any Language", elem_classes=["section-header"])
149
 
@@ -220,6 +235,27 @@ with gr.Blocks(theme=gr.themes.Monochrome(), css=CUSTOM_CSS) as demo:
220
  outputs=[text_display, text_markdown]
221
  )
222
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  # --- Text Interpertation ---
224
  with gr.Tab("🎓 Interpretation"):
225
  gr.Markdown("### Configure Interpretation Settings")
 
4
  from process.interpretation import get_interpretation
5
  from process.translation import get_translaton
6
  from process.gradio_css import CUSTOM_CSS
7
+ from process.agent import AutomatedAnalysisAgent
8
 
9
 
10
  MISTRAL_API_KEY = ""
 
145
  yield "not implemented yet"
146
 
147
 
148
+ def agent_workflow(text: str, prof_language: str, mistral_key: str, gemini_key: str):
149
+ if not mistral_key or not gemini_key:
150
+ return "Error: Both Mistral and Gemini API keys are required."
151
+ if not text or not text.strip():
152
+ return "Error: Input text is empty."
153
+
154
+ try:
155
+ agent = AutomatedAnalysisAgent(mistral_key=mistral_key, gemini_key=gemini_key)
156
+ result = agent.run(text, prof_language=prof_language)
157
+ return result
158
+ except Exception as e:
159
+ return f"An error occurred in the agent workflow: {e}"
160
+
161
+
162
  with gr.Blocks(theme=gr.themes.Monochrome(), css=CUSTOM_CSS) as demo:
163
  gr.Markdown("# 📚 LogosAI - Intensive Reading in Any Language", elem_classes=["section-header"])
164
 
 
235
  outputs=[text_display, text_markdown]
236
  )
237
 
238
+ # --- Agent ---
239
+ with gr.Tab("✨ Agent"):
240
+ gr.Markdown("### Automated Analysis")
241
+ with gr.Row():
242
+ with gr.Column(scale=1):
243
+ agent_prof_language_selector = gr.Dropdown(["AR", "DE", "ES", "EN", "FR", "IT", "JA", "RU", "ZH"], label="Prof's Language", value="EN")
244
+ agent_run_button = gr.Button("Run Automated Analysis", variant="primary")
245
+ with gr.Column(scale=2):
246
+ gr.Markdown("### Agent Result")
247
+ agent_output = gr.Markdown(
248
+ value="*Agent analysis will appear here...*\n\n",
249
+ label="Agent Result"
250
+ )
251
+
252
+ agent_run_button.click(
253
+ fn=agent_workflow,
254
+ inputs=[text_display, agent_prof_language_selector, mistral_api, gemini_api],
255
+ outputs=agent_output
256
+ )
257
+
258
+
259
  # --- Text Interpertation ---
260
  with gr.Tab("🎓 Interpretation"):
261
  gr.Markdown("### Configure Interpretation Settings")
process/agent.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import json
3
+ from google import genai
4
+ from google.genai import types
5
+ from process.ocr import correct_text_with_ai
6
+ from process.interpretation import get_interpretation
7
+
8
+ AGENT_SYS_PROMPT = """
9
+ You are a highly intelligent text analysis agent. Your sole purpose is to analyze a given text and return a JSON object with three keys: "language", "genre", and "correction_needed".
10
+
11
+ 1. **"language"**: Identify the primary language of the text. The value must be one of the following ISO 639-1 codes: ["AR", "DE", "ES", "EN", "FR", "IT", "JA", "RU", "ZH"].
12
+
13
+ 2. **"genre"**: Analyze the text's style, tone, and content to determine its genre. The value must be one of the following strings: ["General", "News", "Philosophy", "Narrative", "Poem", "Paper"].
14
+ * "News": Reports on current events.
15
+ * "Philosophy": Discusses fundamental questions about existence, knowledge, values, reason, mind, and language.
16
+ * "Narrative": Tells a story.
17
+ * "Poem": Uses aesthetic and rhythmic qualities of language.
18
+ * "Paper": A formal academic or scientific paper.
19
+ * "General": Any text that does not fit neatly into the other categories.
20
+
21
+ 3. **"correction_needed"**: Determine if the text contains obvious OCR errors, typos, or significant grammatical mistakes that require correction. The value must be a boolean (`true` or `false`). Set it to `true` if you see scrambled words, weird symbols, or frequent misspellings.
22
+
23
+ Your response MUST be a single, valid JSON object and nothing else. Do not add any explanations, comments, or markdown formatting.
24
+
25
+ Example input text:
26
+ "Teh qick brown fox juumps over teh lazy dog. It was a sunny day in london."
27
+
28
+ Example output:
29
+ {
30
+ "language": "EN",
31
+ "genre": "Narrative",
32
+ "correction_needed": true
33
+ }
34
+ """
35
+
36
+ class AutomatedAnalysisAgent:
37
+ def __init__(self, mistral_key: str, gemini_key: str):
38
+ if not mistral_key or not gemini_key:
39
+ raise ValueError("Both Mistral and Gemini API keys are required.")
40
+ self.mistral_key = mistral_key
41
+ self.gemini_key = gemini_key
42
+ self.genai_client = genai.Client(api_key=self.gemini_key)
43
+
44
+ def _get_analysis_directives(self, text: str) -> dict:
45
+ """
46
+ Analyzes the text to determine language, genre, and if correction is needed.
47
+ """
48
+ try:
49
+ response = self.genai_client.models.generate_content(
50
+ model="gemini-2.5-flash",
51
+ config=types.GenerateContentConfig(
52
+ system_instruction=AGENT_SYS_PROMPT,
53
+ temperature=0.0,
54
+ response_mime_type="application/json",
55
+ ),
56
+ contents=[text]
57
+ )
58
+ directives = json.loads(response.text)
59
+ # Basic validation
60
+ if "language" not in directives or "genre" not in directives or "correction_needed" not in directives:
61
+ raise ValueError("Invalid JSON structure from analysis model.")
62
+ return directives
63
+ except Exception as e:
64
+ # Fallback or error handling
65
+ print(f"Error during analysis: {e}")
66
+ # Provide a default, safe directive
67
+ return {"language": "EN", "genre": "General", "correction_needed": True}
68
+
69
+ def run(self, text: str, prof_language: str = "EN") -> str:
70
+ """
71
+ Runs the full automated analysis and interpretation workflow.
72
+ """
73
+ if not text or not text.strip():
74
+ return "Error: Input text is empty."
75
+
76
+ # 1. Get analysis directives from the agent's brain
77
+ directives = self._get_analysis_directives(text)
78
+
79
+ processed_text = text
80
+ # 2. Conditionally apply AI correction
81
+ if directives.get("correction_needed", False):
82
+ try:
83
+ processed_text = correct_text_with_ai(text, self.mistral_key)
84
+ except Exception as e:
85
+ print(f"Error during AI correction: {e}")
86
+ # Proceed with original text if correction fails
87
+ processed_text = text
88
+
89
+ # 3. Get the final interpretation
90
+ try:
91
+ interpretation = get_interpretation(
92
+ genre=directives.get("genre", "General"),
93
+ api_key=self.gemini_key,
94
+ text=processed_text,
95
+ learn_language=directives.get("language", "EN"),
96
+ prof_language=prof_language
97
+ )
98
+ return interpretation
99
+ except Exception as e:
100
+ print(f"Error during interpretation: {e}")
101
+ return f"An error occurred during the final interpretation step: {e}"
102
+