DocUA commited on
Commit
1d8fcf4
·
1 Parent(s): 8c0cf48

Оновлено моделі Gemini до версії 2.0 у всіх відповідних файлах, включаючи AGENTS.md, INSTRUCTION.md, app.py, requirements.txt та інші. Змінено залежність на google-genai для інтеграції з новим клієнтом. Поліпшено обробку запитів та візуалізацію аналізу.

Browse files
AGENTS.md CHANGED
@@ -83,8 +83,8 @@ class GeminiConnector:
83
  def __init__(self, api_key=None):
84
  self.client = self._init_gemini_client(api_key)
85
  self.models = {
86
- 'analysis': 'gemini-1.5-pro',
87
- 'summary': 'gemini-1.5-flash',
88
  'vision': 'gemini-1.5-pro-vision'
89
  }
90
 
@@ -376,7 +376,7 @@ def create_analysis_visualization(analysis_results):
376
  ```txt
377
  gradio>=4.0.0
378
  markitdown[all]>=0.1.0
379
- google-generativeai>=0.3.0
380
  plotly>=5.0.0
381
  python-multipart>=0.0.6
382
  aiofiles>=22.0.0
@@ -531,4 +531,4 @@ class HFResourceManager:
531
  - ✅ **HF Optimization**: Resource-aware processing
532
  - ✅ **Progressive Enhancement**: Core features first, advanced features additive
533
 
534
- This revised architecture prioritizes **deployment simplicity** while maintaining **functional richness** - perfect for HF Spaces environment with Gemini integration.
 
83
  def __init__(self, api_key=None):
84
  self.client = self._init_gemini_client(api_key)
85
  self.models = {
86
+ 'analysis': 'gemini-2.0-pro-exp',
87
+ 'summary': 'gemini-2.0-flash-exp',
88
  'vision': 'gemini-1.5-pro-vision'
89
  }
90
 
 
376
  ```txt
377
  gradio>=4.0.0
378
  markitdown[all]>=0.1.0
379
+ google-genai>=0.1.0
380
  plotly>=5.0.0
381
  python-multipart>=0.0.6
382
  aiofiles>=22.0.0
 
531
  - ✅ **HF Optimization**: Resource-aware processing
532
  - ✅ **Progressive Enhancement**: Core features first, advanced features additive
533
 
534
+ This revised architecture prioritizes **deployment simplicity** while maintaining **functional richness** - perfect for HF Spaces environment with Gemini integration.
INSTRUCTION.md CHANGED
@@ -527,7 +527,7 @@ PROCESSING_TIMEOUT_SECONDS=300
527
  ENABLE_DEBUG_LOGGING=false
528
 
529
  # AI Integration
530
- GEMINI_DEFAULT_MODEL=gemini-1.5-pro
531
  AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT=your-endpoint
532
 
533
  # Performance Tuning
@@ -590,4 +590,4 @@ A: Так, через Advanced Analytics tab можна обробляти кі
590
 
591
  **Версія документа**: 2.0.0 | **Остання редакція**: Вересень 2025
592
 
593
- *Це керівництво відображає current state платформи та буде оновлюватися з новими features та improvements.*
 
527
  ENABLE_DEBUG_LOGGING=false
528
 
529
  # AI Integration
530
+ GEMINI_DEFAULT_MODEL=gemini-2.0-pro-exp
531
  AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT=your-endpoint
532
 
533
  # Performance Tuning
 
590
 
591
  **Версія документа**: 2.0.0 | **Остання редакція**: Вересень 2025
592
 
593
+ *Це керівництво відображає current state платформи та буде оновлюватися з новими features та improvements.*
README.md CHANGED
@@ -80,7 +80,7 @@ A comprehensive testing platform for Microsoft's MarkItDown document conversion
80
  ```python
81
  gradio>=4.0.0 # UI framework
82
  markitdown[all]>=0.1.0 # Document conversion
83
- google-generativeai>=0.3.0 # Gemini integration
84
  plotly>=5.17.0 # Interactive visualizations
85
  pandas>=1.5.0 # Data processing
86
  ```
@@ -258,4 +258,4 @@ A: Scores are based on structural analysis and AI evaluation. Use as guidelines
258
 
259
  **Built with ❤️ for enterprise document processing**
260
 
261
- *Last updated: September 2025*
 
80
  ```python
81
  gradio>=4.0.0 # UI framework
82
  markitdown[all]>=0.1.0 # Document conversion
83
+ google-genai>=0.1.0 # Gemini integration (new client)
84
  plotly>=5.17.0 # Interactive visualizations
85
  pandas>=1.5.0 # Data processing
86
  ```
 
258
 
259
  **Built with ❤️ for enterprise document processing**
260
 
261
+ *Last updated: September 2025*
app.py CHANGED
@@ -70,7 +70,7 @@ class ProcessingRequest:
70
  file_metadata: JSONDict
71
  gemini_api_key: Optional[str] = None
72
  analysis_type: str = "quality_analysis"
73
- model_preference: str = "gemini-1.5-pro"
74
  enable_plugins: bool = False
75
  azure_endpoint: Optional[str] = None
76
  session_context: JSONDict = field(default_factory=dict)
@@ -316,7 +316,7 @@ class DocumentProcessingOrchestrator:
316
  analysis_request = AnalysisRequest(
317
  content=conversion_result.content,
318
  analysis_type=AnalysisType(request.analysis_type),
319
- model=GeminiModel(request.model_preference)
320
  )
321
 
322
  analysis_result = await engine.analyze_content(analysis_request)
@@ -645,10 +645,13 @@ class MarkItDownTestingApp:
645
 
646
  model_preference = gr.Dropdown(
647
  choices=[
648
- ("Gemini 1.5 Pro (Best Quality)", "gemini-1.5-pro"),
649
- ("Gemini 1.5 Flash (Faster)", "gemini-1.5-flash")
 
 
 
650
  ],
651
- value="gemini-1.5-pro",
652
  label="AI Model Preference"
653
  )
654
 
 
70
  file_metadata: JSONDict
71
  gemini_api_key: Optional[str] = None
72
  analysis_type: str = "quality_analysis"
73
+ model_preference: str = GeminiModel.PRO.value
74
  enable_plugins: bool = False
75
  azure_endpoint: Optional[str] = None
76
  session_context: JSONDict = field(default_factory=dict)
 
316
  analysis_request = AnalysisRequest(
317
  content=conversion_result.content,
318
  analysis_type=AnalysisType(request.analysis_type),
319
+ model=GeminiModel.from_str(request.model_preference)
320
  )
321
 
322
  analysis_result = await engine.analyze_content(analysis_request)
 
645
 
646
  model_preference = gr.Dropdown(
647
  choices=[
648
+ ("Gemini 2.0 Pro (Advanced Reasoning)", GeminiModel.PRO.value),
649
+ ("Gemini 2.0 Flash (Fast Inference)", GeminiModel.FLASH.value),
650
+ ("Gemini 2.5 Flash (Enhanced Quality)", GeminiModel.FLASH_25.value),
651
+ ("Gemini 1.5 Pro (Legacy)", GeminiModel.LEGACY_PRO.value),
652
+ ("Gemini 1.5 Flash (Legacy)", GeminiModel.LEGACY_FLASH.value)
653
  ],
654
+ value=GeminiModel.PRO.value,
655
  label="AI Model Preference"
656
  )
657
 
core/modules.py CHANGED
@@ -26,7 +26,6 @@ from contextlib import asynccontextmanager
26
 
27
  import aiofiles
28
  from markitdown import MarkItDown
29
- import google.generativeai as genai
30
  from tenacity import retry, stop_after_attempt, wait_exponential
31
  try:
32
  import magic
 
26
 
27
  import aiofiles
28
  from markitdown import MarkItDown
 
29
  from tenacity import retry, stop_after_attempt, wait_exponential
30
  try:
31
  import magic
examples/usage_examples.py CHANGED
@@ -218,7 +218,11 @@ async def process_document(file_path, api_key):
218
  ],
219
  "ai_analysis": {
220
  "enabled": True,
221
- "models": ["gemini-1.5-pro", "gemini-1.5-flash"],
 
 
 
 
222
  "analysis_types": [
223
  "quality_analysis",
224
  "structure_review",
@@ -1156,4 +1160,4 @@ async def main():
1156
 
1157
 
1158
  if __name__ == "__main__":
1159
- asyncio.run(main())
 
218
  ],
219
  "ai_analysis": {
220
  "enabled": True,
221
+ "models": [
222
+ "gemini-2.0-pro-exp",
223
+ "gemini-2.0-flash-exp",
224
+ "gemini-2.5-flash"
225
+ ],
226
  "analysis_types": [
227
  "quality_analysis",
228
  "structure_review",
 
1160
 
1161
 
1162
  if __name__ == "__main__":
1163
+ asyncio.run(main())
llm/gemini_connector.py CHANGED
@@ -19,8 +19,9 @@ from typing import Dict, Any, List, Optional, Union, AsyncGenerator
19
  from dataclasses import dataclass, asdict
20
  from enum import Enum
21
 
22
- import google.generativeai as genai
23
- from google.generativeai.types import HarmCategory, HarmBlockThreshold
 
24
  from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
25
  from pydantic import BaseModel, Field, validator, JsonValue
26
 
@@ -40,9 +41,37 @@ class AnalysisType(Enum):
40
 
41
  class GeminiModel(Enum):
42
  """Available Gemini models with strategic use case mapping"""
43
- PRO = "gemini-1.5-pro" # Complex analysis, reasoning
44
- FLASH = "gemini-1.5-flash" # Fast processing, summaries
45
- PRO_VISION = "gemini-1.5-pro-vision" # Multimodal content analysis
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
 
48
  @dataclass
@@ -54,16 +83,28 @@ class GeminiConfig:
54
  temperature: float = 0.1 # Low temperature for consistent analysis
55
  timeout_seconds: int = 60
56
  max_retry_attempts: int = 3
57
- safety_settings: Optional[Dict] = None
58
 
59
  def __post_init__(self):
60
  if self.safety_settings is None:
61
- self.safety_settings = {
62
- HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
63
- HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
64
- HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
65
- HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
66
- }
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
 
69
  class AnalysisRequest(BaseModel):
@@ -81,6 +122,10 @@ class AnalysisRequest(BaseModel):
81
  raise ValueError("Content must be at least 10 characters long")
82
  return v
83
 
 
 
 
 
84
 
85
  class AnalysisResponse(BaseModel):
86
  """Standardized analysis response structure"""
@@ -241,7 +286,7 @@ class GeminiAnalysisEngine:
241
  """Initialize Gemini Analysis Engine with configuration"""
242
 
243
  self.config = config
244
- self.client = None
245
  self._initialize_client()
246
 
247
  # Performance tracking
@@ -256,11 +301,16 @@ class GeminiAnalysisEngine:
256
  raise ValueError("Gemini API key is required")
257
 
258
  try:
259
- genai.configure(api_key=self.config.api_key)
260
- # Test client initialization with a simple call
261
- models = genai.list_models()
262
- logging.info(f"Gemini client initialized successfully. Available models: {len(list(models))}")
263
-
 
 
 
 
 
264
  except Exception as e:
265
  logging.error(f"Failed to initialize Gemini client: {e}")
266
  raise
@@ -287,15 +337,15 @@ class GeminiAnalysisEngine:
287
  try:
288
  # Prepare analysis prompt
289
  prompt = self._build_analysis_prompt(request)
290
-
291
  # Select optimal model for analysis type
292
- model_name = self._select_optimal_model(request.analysis_type, request.model)
293
-
294
  # Execute analysis
295
- response = await self._execute_analysis(model_name, prompt)
296
-
297
  # Parse and structure response
298
- analysis_content = self._parse_analysis_response(response.text, request.analysis_type)
299
 
300
  processing_time = (datetime.now() - start_time).total_seconds()
301
  self.total_processing_time += processing_time
@@ -303,7 +353,7 @@ class GeminiAnalysisEngine:
303
  return AnalysisResponse(
304
  success=True,
305
  analysis_type=request.analysis_type,
306
- model_used=GeminiModel(model_name),
307
  content=analysis_content,
308
  metadata={
309
  'processing_time': processing_time,
@@ -353,9 +403,9 @@ class GeminiAnalysisEngine:
353
 
354
  return f"{system_context}\n\n{main_prompt}"
355
 
356
- def _select_optimal_model(self, analysis_type: AnalysisType, requested_model: GeminiModel) -> str:
357
  """Select optimal Gemini model based on analysis requirements"""
358
-
359
  # Strategic model selection based on analysis complexity
360
  model_recommendations = {
361
  AnalysisType.QUALITY_ANALYSIS: GeminiModel.PRO, # Complex reasoning
@@ -364,38 +414,67 @@ class GeminiAnalysisEngine:
364
  AnalysisType.COMPARATIVE_ANALYSIS: GeminiModel.PRO, # Complex comparison
365
  AnalysisType.EXTRACTION_QUALITY: GeminiModel.PRO, # Detailed quality assessment
366
  }
367
-
368
- # Use recommended model unless specifically overridden
369
- recommended_model = model_recommendations.get(analysis_type, requested_model)
370
- return recommended_model.value
 
 
 
371
 
372
- async def _execute_analysis(self, model_name: str, prompt: str):
373
  """Execute analysis using Gemini API with timeout and error handling"""
374
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  try:
376
- model = genai.GenerativeModel(
377
- model_name=model_name,
378
- safety_settings=self.config.safety_settings
379
- )
380
-
381
- # Configure generation parameters
382
- generation_config = genai.GenerationConfig(
383
- max_output_tokens=self.config.max_tokens,
384
- temperature=self.config.temperature,
385
- )
386
-
387
- # Execute with timeout
388
- response = await asyncio.wait_for(
389
- asyncio.to_thread(
390
- model.generate_content,
391
- prompt,
392
- generation_config=generation_config
393
- ),
394
- timeout=self.config.timeout_seconds
395
  )
396
-
397
- return response
398
-
399
  except asyncio.TimeoutError:
400
  raise TimeoutError(f"Gemini API request timed out after {self.config.timeout_seconds} seconds")
401
  except Exception as e:
@@ -666,7 +745,7 @@ class GeminiConnectionManager:
666
  def create_analysis_request(
667
  content: str,
668
  analysis_type: str,
669
- model: str = "gemini-1.5-pro",
670
  custom_instructions: Optional[str] = None
671
  ) -> AnalysisRequest:
672
  """Factory function for creating analysis requests"""
@@ -674,7 +753,7 @@ def create_analysis_request(
674
  return AnalysisRequest(
675
  content=content,
676
  analysis_type=AnalysisType(analysis_type),
677
- model=GeminiModel(model),
678
  custom_instructions=custom_instructions
679
  )
680
 
 
19
  from dataclasses import dataclass, asdict
20
  from enum import Enum
21
 
22
+ from google import genai
23
+ from google.genai import types
24
+ from google.genai.types import HarmCategory, HarmBlockThreshold
25
  from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
26
  from pydantic import BaseModel, Field, validator, JsonValue
27
 
 
41
 
42
  class GeminiModel(Enum):
43
  """Available Gemini models with strategic use case mapping"""
44
+
45
+ PRO = "gemini-2.0-pro-exp" # Latest high-accuracy reasoning model
46
+ FLASH = "gemini-2.0-flash-exp" # Latest high-speed model
47
+ FLASH_25 = "gemini-2.5-flash" # Enhanced quality flash model
48
+ LEGACY_PRO = "gemini-1.5-pro" # Legacy compatibility
49
+ LEGACY_FLASH = "gemini-1.5-flash" # Legacy compatibility
50
+ PRO_VISION = "gemini-1.5-pro-vision" # Multimodal content analysis
51
+
52
+ @classmethod
53
+ def from_str(cls, value: Union[str, "GeminiModel", None]) -> "GeminiModel":
54
+ """Resolve string input to an enum member with graceful fallbacks"""
55
+
56
+ if isinstance(value, cls):
57
+ return value
58
+
59
+ if value in (None, ""):
60
+ return cls.PRO
61
+
62
+ try:
63
+ return cls(value)
64
+ except ValueError as exc:
65
+ legacy_aliases = {
66
+ "gemini-1.5-pro": cls.LEGACY_PRO,
67
+ "gemini-1.5-flash": cls.LEGACY_FLASH,
68
+ "gemini-1.5-pro-vision": cls.PRO_VISION,
69
+ }
70
+
71
+ if value in legacy_aliases:
72
+ return legacy_aliases[value]
73
+
74
+ raise ValueError(f"Unsupported Gemini model: {value}") from exc
75
 
76
 
77
  @dataclass
 
83
  temperature: float = 0.1 # Low temperature for consistent analysis
84
  timeout_seconds: int = 60
85
  max_retry_attempts: int = 3
86
+ safety_settings: Optional[List[types.SafetySetting]] = None
87
 
88
  def __post_init__(self):
89
  if self.safety_settings is None:
90
+ self.safety_settings = [
91
+ types.SafetySetting(
92
+ category=HarmCategory.HARM_CATEGORY_HATE_SPEECH,
93
+ threshold=HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
94
+ ),
95
+ types.SafetySetting(
96
+ category=HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
97
+ threshold=HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
98
+ ),
99
+ types.SafetySetting(
100
+ category=HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
101
+ threshold=HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
102
+ ),
103
+ types.SafetySetting(
104
+ category=HarmCategory.HARM_CATEGORY_HARASSMENT,
105
+ threshold=HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
106
+ ),
107
+ ]
108
 
109
 
110
  class AnalysisRequest(BaseModel):
 
122
  raise ValueError("Content must be at least 10 characters long")
123
  return v
124
 
125
+ @validator('model', pre=True, always=True)
126
+ def validate_model(cls, value):
127
+ return GeminiModel.from_str(value)
128
+
129
 
130
  class AnalysisResponse(BaseModel):
131
  """Standardized analysis response structure"""
 
286
  """Initialize Gemini Analysis Engine with configuration"""
287
 
288
  self.config = config
289
+ self.client: Optional[genai.Client] = None
290
  self._initialize_client()
291
 
292
  # Performance tracking
 
301
  raise ValueError("Gemini API key is required")
302
 
303
  try:
304
+ self.client = genai.Client(api_key=self.config.api_key)
305
+
306
+ # Optional warm-up to validate credentials without incurring generation cost
307
+ try:
308
+ _ = next(self.client.models.list(page_size=1), None)
309
+ except Exception as list_error: # pragma: no cover - defensive logging
310
+ logging.debug(f"Model listing skipped: {list_error}")
311
+
312
+ logging.info("Gemini client (google-genai) initialized successfully")
313
+
314
  except Exception as e:
315
  logging.error(f"Failed to initialize Gemini client: {e}")
316
  raise
 
337
  try:
338
  # Prepare analysis prompt
339
  prompt = self._build_analysis_prompt(request)
340
+
341
  # Select optimal model for analysis type
342
+ model_enum = self._select_optimal_model(request.analysis_type, request.model)
343
+
344
  # Execute analysis
345
+ response_text = await self._execute_analysis(model_enum.value, prompt)
346
+
347
  # Parse and structure response
348
+ analysis_content = self._parse_analysis_response(response_text, request.analysis_type)
349
 
350
  processing_time = (datetime.now() - start_time).total_seconds()
351
  self.total_processing_time += processing_time
 
353
  return AnalysisResponse(
354
  success=True,
355
  analysis_type=request.analysis_type,
356
+ model_used=model_enum,
357
  content=analysis_content,
358
  metadata={
359
  'processing_time': processing_time,
 
403
 
404
  return f"{system_context}\n\n{main_prompt}"
405
 
406
+ def _select_optimal_model(self, analysis_type: AnalysisType, requested_model: GeminiModel) -> GeminiModel:
407
  """Select optimal Gemini model based on analysis requirements"""
408
+
409
  # Strategic model selection based on analysis complexity
410
  model_recommendations = {
411
  AnalysisType.QUALITY_ANALYSIS: GeminiModel.PRO, # Complex reasoning
 
414
  AnalysisType.COMPARATIVE_ANALYSIS: GeminiModel.PRO, # Complex comparison
415
  AnalysisType.EXTRACTION_QUALITY: GeminiModel.PRO, # Detailed quality assessment
416
  }
417
+
418
+ # Respect explicit model choices outside default presets
419
+ default_overrides = {GeminiModel.PRO, GeminiModel.FLASH}
420
+ if requested_model not in default_overrides:
421
+ return requested_model
422
+
423
+ return model_recommendations.get(analysis_type, requested_model)
424
 
425
+ async def _execute_analysis(self, model_name: str, prompt: str) -> str:
426
  """Execute analysis using Gemini API with timeout and error handling"""
427
+
428
+ if not self.client:
429
+ raise RuntimeError("Gemini client is not initialized")
430
+
431
+ def _run_generation() -> str:
432
+ contents = [
433
+ types.Content(
434
+ role="user",
435
+ parts=[types.Part.from_text(text=prompt)],
436
+ )
437
+ ]
438
+
439
+ config_kwargs = {
440
+ "temperature": self.config.temperature,
441
+ "max_output_tokens": self.config.max_tokens,
442
+ }
443
+
444
+ if self.config.safety_settings:
445
+ config_kwargs["safety_settings"] = self.config.safety_settings
446
+
447
+ generation_config = types.GenerateContentConfig(**config_kwargs)
448
+
449
+ try:
450
+ stream = self.client.models.generate_content_stream(
451
+ model=model_name,
452
+ contents=contents,
453
+ config=generation_config,
454
+ )
455
+
456
+ collected_chunks: List[str] = []
457
+ for chunk in stream:
458
+ text_part = getattr(chunk, "text", None)
459
+ if text_part:
460
+ collected_chunks.append(text_part)
461
+
462
+ return "".join(collected_chunks)
463
+
464
+ except AttributeError:
465
+ response = self.client.models.generate_content(
466
+ model=model_name,
467
+ contents=contents,
468
+ config=generation_config,
469
+ )
470
+ return getattr(response, "text", getattr(response, "output_text", ""))
471
+
472
  try:
473
+ return await asyncio.wait_for(
474
+ asyncio.to_thread(_run_generation),
475
+ timeout=self.config.timeout_seconds,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
476
  )
477
+
 
 
478
  except asyncio.TimeoutError:
479
  raise TimeoutError(f"Gemini API request timed out after {self.config.timeout_seconds} seconds")
480
  except Exception as e:
 
745
  def create_analysis_request(
746
  content: str,
747
  analysis_type: str,
748
+ model: str = GeminiModel.PRO.value,
749
  custom_instructions: Optional[str] = None
750
  ) -> AnalysisRequest:
751
  """Factory function for creating analysis requests"""
 
753
  return AnalysisRequest(
754
  content=content,
755
  analysis_type=AnalysisType(analysis_type),
756
+ model=GeminiModel.from_str(model),
757
  custom_instructions=custom_instructions
758
  )
759
 
requirements.txt CHANGED
@@ -6,7 +6,7 @@ gradio>=4.0.0,<5.0.0 # UI framework - pinned major version fo
6
  markitdown[all]>=0.1.0 # Microsoft's document conversion engine
7
 
8
  # LLM Integration - Gemini Focus
9
- google-generativeai>=0.3.0,<1.0.0 # Google Gemini API client
10
  google-auth>=2.0.0 # Authentication for Google services
11
 
12
  # Data Processing & Visualization
@@ -40,4 +40,4 @@ psutil>=5.9.0 # System resource monitoring
40
  # Development & Testing Dependencies
41
  pytest>=7.0.0 # Testing framework
42
  black>=23.0.0 # Code formatting
43
- flake8>=6.0.0 # Code linting
 
6
  markitdown[all]>=0.1.0 # Microsoft's document conversion engine
7
 
8
  # LLM Integration - Gemini Focus
9
+ google-genai>=0.1.0 # Google Gemini API client (latest)
10
  google-auth>=2.0.0 # Authentication for Google services
11
 
12
  # Data Processing & Visualization
 
40
  # Development & Testing Dependencies
41
  pytest>=7.0.0 # Testing framework
42
  black>=23.0.0 # Code formatting
43
+ flake8>=6.0.0 # Code linting
utils/deployment.py CHANGED
@@ -169,7 +169,7 @@ class SystemHealthChecker:
169
  required_packages = [
170
  'gradio',
171
  'markitdown',
172
- 'google-generativeai',
173
  'plotly',
174
  'pandas',
175
  'numpy',
@@ -412,7 +412,7 @@ class DeploymentValidator:
412
  requirements = f.read()
413
 
414
  # Check for essential packages
415
- essential_packages = ['gradio', 'markitdown', 'google-generativeai']
416
  for package in essential_packages:
417
  if package in requirements:
418
  validation_results['checks'][f'req_{package}'] = True
@@ -606,4 +606,4 @@ def main():
606
 
607
 
608
  if __name__ == "__main__":
609
- main()
 
169
  required_packages = [
170
  'gradio',
171
  'markitdown',
172
+ 'google-genai',
173
  'plotly',
174
  'pandas',
175
  'numpy',
 
412
  requirements = f.read()
413
 
414
  # Check for essential packages
415
+ essential_packages = ['gradio', 'markitdown', 'google-genai']
416
  for package in essential_packages:
417
  if package in requirements:
418
  validation_results['checks'][f'req_{package}'] = True
 
606
 
607
 
608
  if __name__ == "__main__":
609
+ main()