aiecs 1.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. aiecs/__init__.py +72 -0
  2. aiecs/__main__.py +41 -0
  3. aiecs/aiecs_client.py +469 -0
  4. aiecs/application/__init__.py +10 -0
  5. aiecs/application/executors/__init__.py +10 -0
  6. aiecs/application/executors/operation_executor.py +363 -0
  7. aiecs/application/knowledge_graph/__init__.py +7 -0
  8. aiecs/application/knowledge_graph/builder/__init__.py +37 -0
  9. aiecs/application/knowledge_graph/builder/document_builder.py +375 -0
  10. aiecs/application/knowledge_graph/builder/graph_builder.py +356 -0
  11. aiecs/application/knowledge_graph/builder/schema_mapping.py +531 -0
  12. aiecs/application/knowledge_graph/builder/structured_pipeline.py +443 -0
  13. aiecs/application/knowledge_graph/builder/text_chunker.py +319 -0
  14. aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
  15. aiecs/application/knowledge_graph/extractors/base.py +100 -0
  16. aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +327 -0
  17. aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +349 -0
  18. aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +244 -0
  19. aiecs/application/knowledge_graph/fusion/__init__.py +23 -0
  20. aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +387 -0
  21. aiecs/application/knowledge_graph/fusion/entity_linker.py +343 -0
  22. aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +580 -0
  23. aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +189 -0
  24. aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
  25. aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +344 -0
  26. aiecs/application/knowledge_graph/pattern_matching/query_executor.py +378 -0
  27. aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
  28. aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +199 -0
  29. aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
  30. aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
  31. aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +347 -0
  32. aiecs/application/knowledge_graph/reasoning/inference_engine.py +504 -0
  33. aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +167 -0
  34. aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
  35. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
  36. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +630 -0
  37. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +654 -0
  38. aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +477 -0
  39. aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +390 -0
  40. aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +217 -0
  41. aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +169 -0
  42. aiecs/application/knowledge_graph/reasoning/query_planner.py +872 -0
  43. aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +554 -0
  44. aiecs/application/knowledge_graph/retrieval/__init__.py +19 -0
  45. aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +596 -0
  46. aiecs/application/knowledge_graph/search/__init__.py +59 -0
  47. aiecs/application/knowledge_graph/search/hybrid_search.py +423 -0
  48. aiecs/application/knowledge_graph/search/reranker.py +295 -0
  49. aiecs/application/knowledge_graph/search/reranker_strategies.py +553 -0
  50. aiecs/application/knowledge_graph/search/text_similarity.py +398 -0
  51. aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
  52. aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +329 -0
  53. aiecs/application/knowledge_graph/traversal/path_scorer.py +269 -0
  54. aiecs/application/knowledge_graph/validators/__init__.py +13 -0
  55. aiecs/application/knowledge_graph/validators/relation_validator.py +189 -0
  56. aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
  57. aiecs/application/knowledge_graph/visualization/graph_visualizer.py +321 -0
  58. aiecs/common/__init__.py +9 -0
  59. aiecs/common/knowledge_graph/__init__.py +17 -0
  60. aiecs/common/knowledge_graph/runnable.py +484 -0
  61. aiecs/config/__init__.py +16 -0
  62. aiecs/config/config.py +498 -0
  63. aiecs/config/graph_config.py +137 -0
  64. aiecs/config/registry.py +23 -0
  65. aiecs/core/__init__.py +46 -0
  66. aiecs/core/interface/__init__.py +34 -0
  67. aiecs/core/interface/execution_interface.py +152 -0
  68. aiecs/core/interface/storage_interface.py +171 -0
  69. aiecs/domain/__init__.py +289 -0
  70. aiecs/domain/agent/__init__.py +189 -0
  71. aiecs/domain/agent/base_agent.py +697 -0
  72. aiecs/domain/agent/exceptions.py +103 -0
  73. aiecs/domain/agent/graph_aware_mixin.py +559 -0
  74. aiecs/domain/agent/hybrid_agent.py +490 -0
  75. aiecs/domain/agent/integration/__init__.py +26 -0
  76. aiecs/domain/agent/integration/context_compressor.py +222 -0
  77. aiecs/domain/agent/integration/context_engine_adapter.py +252 -0
  78. aiecs/domain/agent/integration/retry_policy.py +219 -0
  79. aiecs/domain/agent/integration/role_config.py +213 -0
  80. aiecs/domain/agent/knowledge_aware_agent.py +646 -0
  81. aiecs/domain/agent/lifecycle.py +296 -0
  82. aiecs/domain/agent/llm_agent.py +300 -0
  83. aiecs/domain/agent/memory/__init__.py +12 -0
  84. aiecs/domain/agent/memory/conversation.py +197 -0
  85. aiecs/domain/agent/migration/__init__.py +14 -0
  86. aiecs/domain/agent/migration/conversion.py +160 -0
  87. aiecs/domain/agent/migration/legacy_wrapper.py +90 -0
  88. aiecs/domain/agent/models.py +317 -0
  89. aiecs/domain/agent/observability.py +407 -0
  90. aiecs/domain/agent/persistence.py +289 -0
  91. aiecs/domain/agent/prompts/__init__.py +29 -0
  92. aiecs/domain/agent/prompts/builder.py +161 -0
  93. aiecs/domain/agent/prompts/formatters.py +189 -0
  94. aiecs/domain/agent/prompts/template.py +255 -0
  95. aiecs/domain/agent/registry.py +260 -0
  96. aiecs/domain/agent/tool_agent.py +257 -0
  97. aiecs/domain/agent/tools/__init__.py +12 -0
  98. aiecs/domain/agent/tools/schema_generator.py +221 -0
  99. aiecs/domain/community/__init__.py +155 -0
  100. aiecs/domain/community/agent_adapter.py +477 -0
  101. aiecs/domain/community/analytics.py +481 -0
  102. aiecs/domain/community/collaborative_workflow.py +642 -0
  103. aiecs/domain/community/communication_hub.py +645 -0
  104. aiecs/domain/community/community_builder.py +320 -0
  105. aiecs/domain/community/community_integration.py +800 -0
  106. aiecs/domain/community/community_manager.py +813 -0
  107. aiecs/domain/community/decision_engine.py +879 -0
  108. aiecs/domain/community/exceptions.py +225 -0
  109. aiecs/domain/community/models/__init__.py +33 -0
  110. aiecs/domain/community/models/community_models.py +268 -0
  111. aiecs/domain/community/resource_manager.py +457 -0
  112. aiecs/domain/community/shared_context_manager.py +603 -0
  113. aiecs/domain/context/__init__.py +58 -0
  114. aiecs/domain/context/context_engine.py +989 -0
  115. aiecs/domain/context/conversation_models.py +354 -0
  116. aiecs/domain/context/graph_memory.py +467 -0
  117. aiecs/domain/execution/__init__.py +12 -0
  118. aiecs/domain/execution/model.py +57 -0
  119. aiecs/domain/knowledge_graph/__init__.py +19 -0
  120. aiecs/domain/knowledge_graph/models/__init__.py +52 -0
  121. aiecs/domain/knowledge_graph/models/entity.py +130 -0
  122. aiecs/domain/knowledge_graph/models/evidence.py +194 -0
  123. aiecs/domain/knowledge_graph/models/inference_rule.py +186 -0
  124. aiecs/domain/knowledge_graph/models/path.py +179 -0
  125. aiecs/domain/knowledge_graph/models/path_pattern.py +173 -0
  126. aiecs/domain/knowledge_graph/models/query.py +272 -0
  127. aiecs/domain/knowledge_graph/models/query_plan.py +187 -0
  128. aiecs/domain/knowledge_graph/models/relation.py +136 -0
  129. aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
  130. aiecs/domain/knowledge_graph/schema/entity_type.py +135 -0
  131. aiecs/domain/knowledge_graph/schema/graph_schema.py +271 -0
  132. aiecs/domain/knowledge_graph/schema/property_schema.py +155 -0
  133. aiecs/domain/knowledge_graph/schema/relation_type.py +171 -0
  134. aiecs/domain/knowledge_graph/schema/schema_manager.py +496 -0
  135. aiecs/domain/knowledge_graph/schema/type_enums.py +205 -0
  136. aiecs/domain/task/__init__.py +13 -0
  137. aiecs/domain/task/dsl_processor.py +613 -0
  138. aiecs/domain/task/model.py +62 -0
  139. aiecs/domain/task/task_context.py +268 -0
  140. aiecs/infrastructure/__init__.py +24 -0
  141. aiecs/infrastructure/graph_storage/__init__.py +11 -0
  142. aiecs/infrastructure/graph_storage/base.py +601 -0
  143. aiecs/infrastructure/graph_storage/batch_operations.py +449 -0
  144. aiecs/infrastructure/graph_storage/cache.py +429 -0
  145. aiecs/infrastructure/graph_storage/distributed.py +226 -0
  146. aiecs/infrastructure/graph_storage/error_handling.py +390 -0
  147. aiecs/infrastructure/graph_storage/graceful_degradation.py +306 -0
  148. aiecs/infrastructure/graph_storage/health_checks.py +378 -0
  149. aiecs/infrastructure/graph_storage/in_memory.py +514 -0
  150. aiecs/infrastructure/graph_storage/index_optimization.py +483 -0
  151. aiecs/infrastructure/graph_storage/lazy_loading.py +410 -0
  152. aiecs/infrastructure/graph_storage/metrics.py +357 -0
  153. aiecs/infrastructure/graph_storage/migration.py +413 -0
  154. aiecs/infrastructure/graph_storage/pagination.py +471 -0
  155. aiecs/infrastructure/graph_storage/performance_monitoring.py +466 -0
  156. aiecs/infrastructure/graph_storage/postgres.py +871 -0
  157. aiecs/infrastructure/graph_storage/query_optimizer.py +635 -0
  158. aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
  159. aiecs/infrastructure/graph_storage/sqlite.py +623 -0
  160. aiecs/infrastructure/graph_storage/streaming.py +495 -0
  161. aiecs/infrastructure/messaging/__init__.py +13 -0
  162. aiecs/infrastructure/messaging/celery_task_manager.py +383 -0
  163. aiecs/infrastructure/messaging/websocket_manager.py +298 -0
  164. aiecs/infrastructure/monitoring/__init__.py +34 -0
  165. aiecs/infrastructure/monitoring/executor_metrics.py +174 -0
  166. aiecs/infrastructure/monitoring/global_metrics_manager.py +213 -0
  167. aiecs/infrastructure/monitoring/structured_logger.py +48 -0
  168. aiecs/infrastructure/monitoring/tracing_manager.py +410 -0
  169. aiecs/infrastructure/persistence/__init__.py +24 -0
  170. aiecs/infrastructure/persistence/context_engine_client.py +187 -0
  171. aiecs/infrastructure/persistence/database_manager.py +333 -0
  172. aiecs/infrastructure/persistence/file_storage.py +754 -0
  173. aiecs/infrastructure/persistence/redis_client.py +220 -0
  174. aiecs/llm/__init__.py +86 -0
  175. aiecs/llm/callbacks/__init__.py +11 -0
  176. aiecs/llm/callbacks/custom_callbacks.py +264 -0
  177. aiecs/llm/client_factory.py +420 -0
  178. aiecs/llm/clients/__init__.py +33 -0
  179. aiecs/llm/clients/base_client.py +193 -0
  180. aiecs/llm/clients/googleai_client.py +181 -0
  181. aiecs/llm/clients/openai_client.py +131 -0
  182. aiecs/llm/clients/vertex_client.py +437 -0
  183. aiecs/llm/clients/xai_client.py +184 -0
  184. aiecs/llm/config/__init__.py +51 -0
  185. aiecs/llm/config/config_loader.py +275 -0
  186. aiecs/llm/config/config_validator.py +236 -0
  187. aiecs/llm/config/model_config.py +151 -0
  188. aiecs/llm/utils/__init__.py +10 -0
  189. aiecs/llm/utils/validate_config.py +91 -0
  190. aiecs/main.py +363 -0
  191. aiecs/scripts/__init__.py +3 -0
  192. aiecs/scripts/aid/VERSION_MANAGEMENT.md +97 -0
  193. aiecs/scripts/aid/__init__.py +19 -0
  194. aiecs/scripts/aid/version_manager.py +215 -0
  195. aiecs/scripts/dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md +242 -0
  196. aiecs/scripts/dependance_check/README_DEPENDENCY_CHECKER.md +310 -0
  197. aiecs/scripts/dependance_check/__init__.py +17 -0
  198. aiecs/scripts/dependance_check/dependency_checker.py +938 -0
  199. aiecs/scripts/dependance_check/dependency_fixer.py +391 -0
  200. aiecs/scripts/dependance_check/download_nlp_data.py +396 -0
  201. aiecs/scripts/dependance_check/quick_dependency_check.py +270 -0
  202. aiecs/scripts/dependance_check/setup_nlp_data.sh +217 -0
  203. aiecs/scripts/dependance_patch/__init__.py +7 -0
  204. aiecs/scripts/dependance_patch/fix_weasel/README_WEASEL_PATCH.md +126 -0
  205. aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
  206. aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.py +128 -0
  207. aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.sh +82 -0
  208. aiecs/scripts/dependance_patch/fix_weasel/patch_weasel_library.sh +188 -0
  209. aiecs/scripts/dependance_patch/fix_weasel/run_weasel_patch.sh +41 -0
  210. aiecs/scripts/tools_develop/README.md +449 -0
  211. aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
  212. aiecs/scripts/tools_develop/__init__.py +21 -0
  213. aiecs/scripts/tools_develop/check_type_annotations.py +259 -0
  214. aiecs/scripts/tools_develop/validate_tool_schemas.py +422 -0
  215. aiecs/scripts/tools_develop/verify_tools.py +356 -0
  216. aiecs/tasks/__init__.py +1 -0
  217. aiecs/tasks/worker.py +172 -0
  218. aiecs/tools/__init__.py +299 -0
  219. aiecs/tools/apisource/__init__.py +99 -0
  220. aiecs/tools/apisource/intelligence/__init__.py +19 -0
  221. aiecs/tools/apisource/intelligence/data_fusion.py +381 -0
  222. aiecs/tools/apisource/intelligence/query_analyzer.py +413 -0
  223. aiecs/tools/apisource/intelligence/search_enhancer.py +388 -0
  224. aiecs/tools/apisource/monitoring/__init__.py +9 -0
  225. aiecs/tools/apisource/monitoring/metrics.py +303 -0
  226. aiecs/tools/apisource/providers/__init__.py +115 -0
  227. aiecs/tools/apisource/providers/base.py +664 -0
  228. aiecs/tools/apisource/providers/census.py +401 -0
  229. aiecs/tools/apisource/providers/fred.py +564 -0
  230. aiecs/tools/apisource/providers/newsapi.py +412 -0
  231. aiecs/tools/apisource/providers/worldbank.py +357 -0
  232. aiecs/tools/apisource/reliability/__init__.py +12 -0
  233. aiecs/tools/apisource/reliability/error_handler.py +375 -0
  234. aiecs/tools/apisource/reliability/fallback_strategy.py +391 -0
  235. aiecs/tools/apisource/tool.py +850 -0
  236. aiecs/tools/apisource/utils/__init__.py +9 -0
  237. aiecs/tools/apisource/utils/validators.py +338 -0
  238. aiecs/tools/base_tool.py +201 -0
  239. aiecs/tools/docs/__init__.py +121 -0
  240. aiecs/tools/docs/ai_document_orchestrator.py +599 -0
  241. aiecs/tools/docs/ai_document_writer_orchestrator.py +2403 -0
  242. aiecs/tools/docs/content_insertion_tool.py +1333 -0
  243. aiecs/tools/docs/document_creator_tool.py +1317 -0
  244. aiecs/tools/docs/document_layout_tool.py +1166 -0
  245. aiecs/tools/docs/document_parser_tool.py +994 -0
  246. aiecs/tools/docs/document_writer_tool.py +1818 -0
  247. aiecs/tools/knowledge_graph/__init__.py +17 -0
  248. aiecs/tools/knowledge_graph/graph_reasoning_tool.py +734 -0
  249. aiecs/tools/knowledge_graph/graph_search_tool.py +923 -0
  250. aiecs/tools/knowledge_graph/kg_builder_tool.py +476 -0
  251. aiecs/tools/langchain_adapter.py +542 -0
  252. aiecs/tools/schema_generator.py +275 -0
  253. aiecs/tools/search_tool/__init__.py +100 -0
  254. aiecs/tools/search_tool/analyzers.py +589 -0
  255. aiecs/tools/search_tool/cache.py +260 -0
  256. aiecs/tools/search_tool/constants.py +128 -0
  257. aiecs/tools/search_tool/context.py +216 -0
  258. aiecs/tools/search_tool/core.py +749 -0
  259. aiecs/tools/search_tool/deduplicator.py +123 -0
  260. aiecs/tools/search_tool/error_handler.py +271 -0
  261. aiecs/tools/search_tool/metrics.py +371 -0
  262. aiecs/tools/search_tool/rate_limiter.py +178 -0
  263. aiecs/tools/search_tool/schemas.py +277 -0
  264. aiecs/tools/statistics/__init__.py +80 -0
  265. aiecs/tools/statistics/ai_data_analysis_orchestrator.py +643 -0
  266. aiecs/tools/statistics/ai_insight_generator_tool.py +505 -0
  267. aiecs/tools/statistics/ai_report_orchestrator_tool.py +694 -0
  268. aiecs/tools/statistics/data_loader_tool.py +564 -0
  269. aiecs/tools/statistics/data_profiler_tool.py +658 -0
  270. aiecs/tools/statistics/data_transformer_tool.py +573 -0
  271. aiecs/tools/statistics/data_visualizer_tool.py +495 -0
  272. aiecs/tools/statistics/model_trainer_tool.py +487 -0
  273. aiecs/tools/statistics/statistical_analyzer_tool.py +459 -0
  274. aiecs/tools/task_tools/__init__.py +86 -0
  275. aiecs/tools/task_tools/chart_tool.py +732 -0
  276. aiecs/tools/task_tools/classfire_tool.py +922 -0
  277. aiecs/tools/task_tools/image_tool.py +447 -0
  278. aiecs/tools/task_tools/office_tool.py +684 -0
  279. aiecs/tools/task_tools/pandas_tool.py +635 -0
  280. aiecs/tools/task_tools/report_tool.py +635 -0
  281. aiecs/tools/task_tools/research_tool.py +392 -0
  282. aiecs/tools/task_tools/scraper_tool.py +715 -0
  283. aiecs/tools/task_tools/stats_tool.py +688 -0
  284. aiecs/tools/temp_file_manager.py +130 -0
  285. aiecs/tools/tool_executor/__init__.py +37 -0
  286. aiecs/tools/tool_executor/tool_executor.py +881 -0
  287. aiecs/utils/LLM_output_structor.py +445 -0
  288. aiecs/utils/__init__.py +34 -0
  289. aiecs/utils/base_callback.py +47 -0
  290. aiecs/utils/cache_provider.py +695 -0
  291. aiecs/utils/execution_utils.py +184 -0
  292. aiecs/utils/logging.py +1 -0
  293. aiecs/utils/prompt_loader.py +14 -0
  294. aiecs/utils/token_usage_repository.py +323 -0
  295. aiecs/ws/__init__.py +0 -0
  296. aiecs/ws/socket_server.py +52 -0
  297. aiecs-1.5.1.dist-info/METADATA +608 -0
  298. aiecs-1.5.1.dist-info/RECORD +302 -0
  299. aiecs-1.5.1.dist-info/WHEEL +5 -0
  300. aiecs-1.5.1.dist-info/entry_points.txt +10 -0
  301. aiecs-1.5.1.dist-info/licenses/LICENSE +225 -0
  302. aiecs-1.5.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,181 @@
1
+ import logging
2
+ import os
3
+ from typing import Optional, List, AsyncGenerator
4
+
5
+ import google.generativeai as genai
6
+ from google.generativeai.types import (
7
+ GenerationConfig,
8
+ HarmCategory,
9
+ HarmBlockThreshold,
10
+ )
11
+
12
+ from aiecs.llm.clients.base_client import (
13
+ BaseLLMClient,
14
+ LLMMessage,
15
+ LLMResponse,
16
+ ProviderNotAvailableError,
17
+ RateLimitError,
18
+ )
19
+ from aiecs.config.config import get_settings
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ class GoogleAIClient(BaseLLMClient):
25
+ """Google AI (Gemini) provider client"""
26
+
27
+ def __init__(self):
28
+ super().__init__("GoogleAI")
29
+ self.settings = get_settings()
30
+ self._initialized = False
31
+ self.client = None
32
+
33
+ def _init_google_ai(self):
34
+ """Lazy initialization of Google AI SDK"""
35
+ if not self._initialized:
36
+ api_key = self.settings.googleai_api_key or os.environ.get("GOOGLEAI_API_KEY")
37
+ if not api_key:
38
+ raise ProviderNotAvailableError(
39
+ "Google AI API key not configured. Set GOOGLEAI_API_KEY."
40
+ )
41
+
42
+ try:
43
+ genai.configure(api_key=api_key)
44
+ self._initialized = True
45
+ self.logger.info("Google AI SDK initialized successfully.")
46
+ except Exception as e:
47
+ raise ProviderNotAvailableError(f"Failed to initialize Google AI SDK: {str(e)}")
48
+
49
+ async def generate_text(
50
+ self,
51
+ messages: List[LLMMessage],
52
+ model: Optional[str] = None,
53
+ temperature: float = 0.7,
54
+ max_tokens: Optional[int] = None,
55
+ **kwargs,
56
+ ) -> LLMResponse:
57
+ """Generate text using Google AI"""
58
+ self._init_google_ai()
59
+
60
+ # Get model name from config if not provided
61
+ model_name = model or self._get_default_model() or "gemini-2.5-pro"
62
+
63
+ # Get model config for default parameters
64
+ model_config = self._get_model_config(model_name)
65
+ if model_config and max_tokens is None:
66
+ max_tokens = model_config.default_params.max_tokens
67
+
68
+ try:
69
+ model_instance = genai.GenerativeModel(model_name)
70
+
71
+ # Convert messages to Google AI format
72
+ history = [{"role": msg.role, "parts": [msg.content]} for msg in messages]
73
+
74
+ # The last message is the prompt
75
+ prompt = history.pop()
76
+
77
+ # Create GenerationConfig
78
+ generation_config = GenerationConfig(
79
+ temperature=temperature,
80
+ max_output_tokens=max_tokens or 8192,
81
+ top_p=kwargs.get("top_p", 0.95),
82
+ top_k=kwargs.get("top_k", 40),
83
+ )
84
+
85
+ # Safety settings to match vertex_client
86
+ safety_settings = {
87
+ HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_NONE,
88
+ HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_NONE,
89
+ HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_NONE,
90
+ HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_NONE,
91
+ }
92
+
93
+ response = await model_instance.generate_content_async(
94
+ contents=prompt["parts"],
95
+ generation_config=generation_config,
96
+ safety_settings=safety_settings,
97
+ )
98
+
99
+ content = response.text
100
+ prompt_tokens = response.usage_metadata.prompt_token_count
101
+ completion_tokens = response.usage_metadata.candidates_token_count
102
+ total_tokens = response.usage_metadata.total_token_count
103
+
104
+ # Use config-based cost estimation
105
+ cost = self._estimate_cost_from_config(model_name, prompt_tokens, completion_tokens)
106
+
107
+ return LLMResponse(
108
+ content=content,
109
+ provider=self.provider_name,
110
+ model=model_name,
111
+ tokens_used=total_tokens,
112
+ prompt_tokens=prompt_tokens,
113
+ completion_tokens=completion_tokens,
114
+ cost_estimate=cost,
115
+ )
116
+
117
+ except Exception as e:
118
+ if "quota" in str(e).lower():
119
+ raise RateLimitError(f"Google AI quota exceeded: {str(e)}")
120
+ self.logger.error(f"Error generating text with Google AI: {e}")
121
+ raise
122
+
123
+ async def stream_text(
124
+ self,
125
+ messages: List[LLMMessage],
126
+ model: Optional[str] = None,
127
+ temperature: float = 0.7,
128
+ max_tokens: Optional[int] = None,
129
+ **kwargs,
130
+ ) -> AsyncGenerator[str, None]:
131
+ """Stream text generation using Google AI"""
132
+ self._init_google_ai()
133
+
134
+ # Get model name from config if not provided
135
+ model_name = model or self._get_default_model() or "gemini-2.5-pro"
136
+
137
+ # Get model config for default parameters
138
+ model_config = self._get_model_config(model_name)
139
+ if model_config and max_tokens is None:
140
+ max_tokens = model_config.default_params.max_tokens
141
+
142
+ try:
143
+ model_instance = genai.GenerativeModel(model_name)
144
+
145
+ # Convert messages to Google AI format
146
+ history = [{"role": msg.role, "parts": [msg.content]} for msg in messages]
147
+ prompt = history.pop()
148
+
149
+ generation_config = GenerationConfig(
150
+ temperature=temperature,
151
+ max_output_tokens=max_tokens or 8192,
152
+ top_p=kwargs.get("top_p", 0.95),
153
+ top_k=kwargs.get("top_k", 40),
154
+ )
155
+
156
+ safety_settings = {
157
+ HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_NONE,
158
+ HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_NONE,
159
+ HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_NONE,
160
+ HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_NONE,
161
+ }
162
+
163
+ response_stream = await model_instance.generate_content_async(
164
+ contents=prompt["parts"],
165
+ generation_config=generation_config,
166
+ safety_settings=safety_settings,
167
+ stream=True,
168
+ )
169
+
170
+ async for chunk in response_stream:
171
+ if chunk.text:
172
+ yield chunk.text
173
+
174
+ except Exception as e:
175
+ self.logger.error(f"Error streaming text with Google AI: {e}")
176
+ raise
177
+
178
+ async def close(self):
179
+ """Clean up resources"""
180
+ # Google AI SDK does not require explicit closing of a client
181
+ self._initialized = False
@@ -0,0 +1,131 @@
1
+ import logging
2
+ from typing import Optional, List, AsyncGenerator
3
+ from openai import AsyncOpenAI
4
+ from tenacity import (
5
+ retry,
6
+ stop_after_attempt,
7
+ wait_exponential,
8
+ retry_if_exception_type,
9
+ )
10
+ import httpx
11
+
12
+ from aiecs.llm.clients.base_client import (
13
+ BaseLLMClient,
14
+ LLMMessage,
15
+ LLMResponse,
16
+ ProviderNotAvailableError,
17
+ RateLimitError,
18
+ )
19
+ from aiecs.config.config import get_settings
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ class OpenAIClient(BaseLLMClient):
25
+ """OpenAI provider client"""
26
+
27
+ def __init__(self):
28
+ super().__init__("OpenAI")
29
+ self.settings = get_settings()
30
+ self._client: Optional[AsyncOpenAI] = None
31
+
32
+ def _get_client(self) -> AsyncOpenAI:
33
+ """Lazy initialization of OpenAI client"""
34
+ if not self._client:
35
+ if not self.settings.openai_api_key:
36
+ raise ProviderNotAvailableError("OpenAI API key not configured")
37
+ self._client = AsyncOpenAI(api_key=self.settings.openai_api_key)
38
+ return self._client
39
+
40
+ @retry(
41
+ stop=stop_after_attempt(3),
42
+ wait=wait_exponential(multiplier=1, min=4, max=10),
43
+ retry=retry_if_exception_type((httpx.RequestError, RateLimitError)),
44
+ )
45
+ async def generate_text(
46
+ self,
47
+ messages: List[LLMMessage],
48
+ model: Optional[str] = None,
49
+ temperature: float = 0.7,
50
+ max_tokens: Optional[int] = None,
51
+ **kwargs,
52
+ ) -> LLMResponse:
53
+ """Generate text using OpenAI API"""
54
+ client = self._get_client()
55
+
56
+ # Get model name from config if not provided
57
+ model = model or self._get_default_model() or "gpt-4-turbo"
58
+
59
+ # Convert to OpenAI message format
60
+ openai_messages = [{"role": msg.role, "content": msg.content} for msg in messages]
61
+
62
+ try:
63
+ response = await client.chat.completions.create(
64
+ model=model,
65
+ messages=openai_messages,
66
+ temperature=temperature,
67
+ max_tokens=max_tokens,
68
+ **kwargs,
69
+ )
70
+
71
+ content = response.choices[0].message.content
72
+ tokens_used = response.usage.total_tokens if response.usage else None
73
+
74
+ # Estimate cost using config
75
+ input_tokens = response.usage.prompt_tokens if response.usage else 0
76
+ output_tokens = response.usage.completion_tokens if response.usage else 0
77
+ cost = self._estimate_cost_from_config(model, input_tokens, output_tokens)
78
+
79
+ return LLMResponse(
80
+ content=content,
81
+ provider=self.provider_name,
82
+ model=model,
83
+ tokens_used=tokens_used,
84
+ cost_estimate=cost,
85
+ )
86
+
87
+ except Exception as e:
88
+ if "rate_limit" in str(e).lower():
89
+ raise RateLimitError(f"OpenAI rate limit exceeded: {str(e)}")
90
+ raise
91
+
92
+ async def stream_text(
93
+ self,
94
+ messages: List[LLMMessage],
95
+ model: Optional[str] = None,
96
+ temperature: float = 0.7,
97
+ max_tokens: Optional[int] = None,
98
+ **kwargs,
99
+ ) -> AsyncGenerator[str, None]:
100
+ """Stream text using OpenAI API"""
101
+ client = self._get_client()
102
+
103
+ # Get model name from config if not provided
104
+ model = model or self._get_default_model() or "gpt-4-turbo"
105
+
106
+ openai_messages = [{"role": msg.role, "content": msg.content} for msg in messages]
107
+
108
+ try:
109
+ stream = await client.chat.completions.create(
110
+ model=model,
111
+ messages=openai_messages,
112
+ temperature=temperature,
113
+ max_tokens=max_tokens,
114
+ stream=True,
115
+ **kwargs,
116
+ )
117
+
118
+ async for chunk in stream:
119
+ if chunk.choices[0].delta.content:
120
+ yield chunk.choices[0].delta.content
121
+
122
+ except Exception as e:
123
+ if "rate_limit" in str(e).lower():
124
+ raise RateLimitError(f"OpenAI rate limit exceeded: {str(e)}")
125
+ raise
126
+
127
+ async def close(self):
128
+ """Clean up resources"""
129
+ if self._client:
130
+ await self._client.close()
131
+ self._client = None