iatoolkit 1.10.0__tar.gz → 1.21.0__tar.gz
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.
- {iatoolkit-1.10.0/src/iatoolkit.egg-info → iatoolkit-1.21.0}/PKG-INFO +1 -1
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/__init__.py +3 -3
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/cli_commands.py +16 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/common/routes.py +6 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/common/util.py +8 -123
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/core.py +3 -2
- iatoolkit-1.21.0/src/iatoolkit/infra/connectors/file_connector.py +28 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +22 -27
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +14 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +32 -1
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/connectors/local_file_connector.py +22 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/connectors/s3_connector.py +27 -1
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +17 -1
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +117 -18
- iatoolkit-1.21.0/src/iatoolkit/infra/llm_providers/openai_adapter.py +219 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/llm_response.py +13 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/locales/en.yaml +87 -2
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/locales/es.yaml +86 -1
- iatoolkit-1.21.0/src/iatoolkit/repositories/document_repo.py +72 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/repositories/llm_query_repo.py +46 -34
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/repositories/models.py +52 -3
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/repositories/vs_repo.py +1 -1
- iatoolkit-1.21.0/src/iatoolkit/services/company_context_service.py +397 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/configuration_service.py +28 -1
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/dispatcher_service.py +1 -1
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/file_processor_service.py +0 -3
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/i18n_service.py +7 -0
- iatoolkit-1.21.0/src/iatoolkit/services/ingestor_service.py +297 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/knowledge_base_service.py +41 -9
- iatoolkit-1.21.0/src/iatoolkit/services/language_service.py +131 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/llm_client_service.py +61 -2
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/prompt_service.py +186 -344
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/query_service.py +49 -20
- iatoolkit-1.21.0/src/iatoolkit/services/storage_service.py +184 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/tool_service.py +3 -2
- iatoolkit-1.21.0/src/iatoolkit/static/js/chat_filepond.js +210 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/js/chat_main.js +105 -52
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +96 -0
- iatoolkit-1.21.0/src/iatoolkit/system_prompts/query_main.prompt +59 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/templates/chat.html +15 -6
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/base_login_view.py +1 -1
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/chat_view.py +1 -1
- iatoolkit-1.21.0/src/iatoolkit/views/ingestion_api_view.py +100 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/login_view.py +1 -1
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/prompt_api_view.py +1 -1
- {iatoolkit-1.10.0 → iatoolkit-1.21.0/src/iatoolkit.egg-info}/PKG-INFO +1 -1
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit.egg-info/SOURCES.txt +3 -1
- iatoolkit-1.10.0/src/iatoolkit/infra/connectors/file_connector.py +0 -17
- iatoolkit-1.10.0/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -124
- iatoolkit-1.10.0/src/iatoolkit/repositories/document_repo.py +0 -40
- iatoolkit-1.10.0/src/iatoolkit/services/company_context_service.py +0 -236
- iatoolkit-1.10.0/src/iatoolkit/services/language_service.py +0 -89
- iatoolkit-1.10.0/src/iatoolkit/services/load_documents_service.py +0 -152
- iatoolkit-1.10.0/src/iatoolkit/static/js/chat_filepond.js +0 -85
- iatoolkit-1.10.0/src/iatoolkit/system_prompts/query_main.prompt +0 -74
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/LICENSE +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/LICENSE_COMMUNITY.md +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/pyproject.toml +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/readme.md +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/requirements.txt +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/setup.cfg +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/base_company.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/common/__init__.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/common/exceptions.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/common/interfaces/__init__.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/common/model_registry.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/common/session_manager.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/company_registry.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/__init__.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/call_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/repositories/__init__.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/repositories/database_manager.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/__init__.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/auth_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/benchmark_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/branding_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/document_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/embedding_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/excel_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/history_manager_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/jwt_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/license_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/mail_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/profile_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/sql_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/styles/documents.css +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/system_prompts/__init__.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/system_prompts/format_styles.prompt +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/system_prompts/sql_rules.prompt +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/templates/_company_header.html +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/templates/_login_widget.html +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/templates/base.html +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/templates/change_password.html +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/templates/chat_modals.html +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/templates/error.html +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/templates/forgot_password.html +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/templates/signup.html +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/__init__.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/categories_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/change_password_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/configuration_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/embedding_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/help_content_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/history_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/home_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/load_document_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/logout_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/profile_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/rag_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/root_redirect_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/signup_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/static_page_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/users_api_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/views/verify_user_view.py +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit.egg-info/requires.txt +0 -0
- {iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit.egg-info/top_level.txt +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#
|
|
4
4
|
# IAToolkit is open source software.
|
|
5
5
|
|
|
6
|
-
__version__ = "1.
|
|
6
|
+
__version__ = "1.21.0"
|
|
7
7
|
|
|
8
8
|
# Expose main classes and functions at the top level of the package
|
|
9
9
|
|
|
@@ -19,7 +19,7 @@ from iatoolkit.services.query_service import QueryService
|
|
|
19
19
|
from iatoolkit.services.document_service import DocumentService
|
|
20
20
|
from iatoolkit.services.knowledge_base_service import KnowledgeBaseService
|
|
21
21
|
from iatoolkit.services.sql_service import SqlService
|
|
22
|
-
from iatoolkit.services.
|
|
22
|
+
from iatoolkit.services.ingestor_service import IngestorService
|
|
23
23
|
from iatoolkit.infra.call_service import CallServiceClient
|
|
24
24
|
from iatoolkit.services.profile_service import ProfileService
|
|
25
25
|
from iatoolkit.services.mail_service import MailService
|
|
@@ -37,7 +37,7 @@ __all__ = [
|
|
|
37
37
|
'SqlService',
|
|
38
38
|
'DocumentService',
|
|
39
39
|
'KnowledgeBaseService',
|
|
40
|
-
'
|
|
40
|
+
'IngestorService',
|
|
41
41
|
'CallServiceClient',
|
|
42
42
|
'ProfileService',
|
|
43
43
|
'MailService',
|
|
@@ -7,6 +7,7 @@ import click
|
|
|
7
7
|
import logging
|
|
8
8
|
from iatoolkit.core import IAToolkit
|
|
9
9
|
from iatoolkit.services.profile_service import ProfileService
|
|
10
|
+
from iatoolkit.services.prompt_service import PromptService
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
def register_core_commands(app):
|
|
@@ -32,6 +33,21 @@ def register_core_commands(app):
|
|
|
32
33
|
logging.exception(e)
|
|
33
34
|
click.echo(f"❌ unexpectd error during the configuration: {e}")
|
|
34
35
|
|
|
36
|
+
@app.cli.command("init-company")
|
|
37
|
+
@click.argument("company_short_name")
|
|
38
|
+
def init_company(company_short_name: str):
|
|
39
|
+
"""⚙️ Bootstrap a new company."""
|
|
40
|
+
try:
|
|
41
|
+
prompt_service = IAToolkit.get_instance().get_injector().get(PromptService)
|
|
42
|
+
click.echo(f"🔑 Bootstrap company: '{company_short_name}'...")
|
|
43
|
+
result = prompt_service.register_system_prompts(company_short_name)
|
|
44
|
+
|
|
45
|
+
if result:
|
|
46
|
+
click.echo("✅ System prompts registered successfully!")
|
|
47
|
+
except Exception as e:
|
|
48
|
+
logging.exception(e)
|
|
49
|
+
click.echo(f"❌ unexpected error during the configuration: {e}")
|
|
50
|
+
|
|
35
51
|
@app.cli.command("encrypt-key")
|
|
36
52
|
@click.argument("key")
|
|
37
53
|
def encrypt_llm_api_key(key: str):
|
|
@@ -33,6 +33,7 @@ def register_views(app):
|
|
|
33
33
|
from iatoolkit.views.users_api_view import UsersApiView
|
|
34
34
|
from iatoolkit.views.rag_api_view import RagApiView
|
|
35
35
|
from iatoolkit.views.categories_api_view import CategoriesApiView
|
|
36
|
+
from iatoolkit.views.ingestion_api_view import IngestionApiView
|
|
36
37
|
|
|
37
38
|
# assign root '/' to our new redirect logic
|
|
38
39
|
app.add_url_rule('/home', view_func=RootRedirectView.as_view('root_redirect'))
|
|
@@ -136,6 +137,11 @@ def register_views(app):
|
|
|
136
137
|
# this endpoint is for upload documents into the vector store (api-key)
|
|
137
138
|
app.add_url_rule('/api/load-document', view_func=LoadDocumentApiView.as_view('load-document'), methods=['POST'])
|
|
138
139
|
|
|
140
|
+
# Document ingestion
|
|
141
|
+
ingestion_view = IngestionApiView.as_view('ingestion_api')
|
|
142
|
+
app.add_url_rule('/<company_short_name>/api/ingestion-sources', view_func=ingestion_view, methods=['GET', 'POST'])
|
|
143
|
+
app.add_url_rule('/<company_short_name>/api/ingestion-sources/<int:source_id>/<action>', view_func=ingestion_view, methods=['POST'])
|
|
144
|
+
|
|
139
145
|
# this endpoint is for generating embeddings for a given text
|
|
140
146
|
app.add_url_rule('/<company_short_name>/api/embedding',
|
|
141
147
|
view_func=EmbeddingApiView.as_view('embedding_api'))
|
|
@@ -162,8 +162,15 @@ class Utility:
|
|
|
162
162
|
Parses a YAML string into a dictionary securely.
|
|
163
163
|
"""
|
|
164
164
|
try:
|
|
165
|
+
if not yaml_content:
|
|
166
|
+
return {}
|
|
167
|
+
|
|
168
|
+
# Normalizar tabulaciones que rompen YAML
|
|
165
169
|
yaml_content = yaml_content.replace('\t', ' ')
|
|
166
|
-
|
|
170
|
+
|
|
171
|
+
loaded = yaml.safe_load(yaml_content)
|
|
172
|
+
# Asegurar que siempre retornamos un dict, incluso si el YAML es una lista o escalar
|
|
173
|
+
return loaded if isinstance(loaded, dict) else {}
|
|
167
174
|
except yaml.YAMLError as e:
|
|
168
175
|
logging.error(f"Error parsing YAML string: {e}")
|
|
169
176
|
return {}
|
|
@@ -182,128 +189,6 @@ class Utility:
|
|
|
182
189
|
raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
|
|
183
190
|
f"Failed to generate YAML: {e}")
|
|
184
191
|
|
|
185
|
-
def generate_context_for_schema(self, entity_name: str, schema_file: str = None, schema: dict = {}) -> str:
|
|
186
|
-
if not schema_file and not schema:
|
|
187
|
-
raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
|
|
188
|
-
f'No se pudo obtener schema de la entidad: {entity_name}')
|
|
189
|
-
|
|
190
|
-
try:
|
|
191
|
-
if schema_file:
|
|
192
|
-
schema = self.load_schema_from_yaml(schema_file)
|
|
193
|
-
table_schema = self.generate_schema_table(schema)
|
|
194
|
-
return table_schema
|
|
195
|
-
except Exception as e:
|
|
196
|
-
logging.exception(e)
|
|
197
|
-
raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
|
|
198
|
-
f'No se pudo leer el schema de la entidad: {entity_name}') from e
|
|
199
|
-
|
|
200
|
-
def generate_schema_table(self, schema: dict) -> str:
|
|
201
|
-
"""
|
|
202
|
-
Genera una descripción detallada y formateada en Markdown de un esquema.
|
|
203
|
-
Esta función está diseñada para manejar el formato específico de nuestros
|
|
204
|
-
archivos YAML, donde el esquema se define bajo una única clave raíz.
|
|
205
|
-
"""
|
|
206
|
-
if not schema or not isinstance(schema, dict):
|
|
207
|
-
return ""
|
|
208
|
-
|
|
209
|
-
# Asumimos que el YAML tiene una única clave raíz que nombra a la entidad.
|
|
210
|
-
if len(schema) == 1:
|
|
211
|
-
root_name = list(schema.keys())[0]
|
|
212
|
-
root_details = schema[root_name]
|
|
213
|
-
|
|
214
|
-
# support this format
|
|
215
|
-
if root_details.get('columns'):
|
|
216
|
-
root_details = root_details['columns']
|
|
217
|
-
|
|
218
|
-
if isinstance(root_details, dict):
|
|
219
|
-
# Las claves de metadatos describen el objeto en sí, no sus propiedades hijas.
|
|
220
|
-
METADATA_KEYS = ['description', 'type', 'format', 'items', 'properties', 'pk']
|
|
221
|
-
|
|
222
|
-
# Las propiedades son las claves restantes en el diccionario.
|
|
223
|
-
properties = {
|
|
224
|
-
k: v for k, v in root_details.items() if k not in METADATA_KEYS
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
# La descripción del objeto raíz.
|
|
228
|
-
root_description = root_details.get('description', '')
|
|
229
|
-
|
|
230
|
-
# Formatea las propiedades extraídas usando la función auxiliar recursiva.
|
|
231
|
-
formatted_properties = self._format_json_schema(properties, 0)
|
|
232
|
-
|
|
233
|
-
# Construcción del resultado final, incluyendo el nombre del objeto raíz.
|
|
234
|
-
output_parts = [f"\n\n### Objeto: `{root_name}`"]
|
|
235
|
-
if root_description:
|
|
236
|
-
# Limpia la descripción para que se muestre bien
|
|
237
|
-
cleaned_description = '\n'.join(line.strip() for line in root_description.strip().split('\n'))
|
|
238
|
-
output_parts.append(f"{cleaned_description}")
|
|
239
|
-
|
|
240
|
-
if formatted_properties:
|
|
241
|
-
output_parts.append(f"**Campos del objeto `{root_name}`:**\n{formatted_properties}")
|
|
242
|
-
|
|
243
|
-
return "\n".join(output_parts)
|
|
244
|
-
|
|
245
|
-
# Si el esquema (como tender_schema.yaml) no tiene un objeto raíz,
|
|
246
|
-
# se formatea directamente como una lista de propiedades.
|
|
247
|
-
return self._format_json_schema(schema, 0)
|
|
248
|
-
|
|
249
|
-
def _format_json_schema(self, properties: dict, indent_level: int) -> str:
|
|
250
|
-
"""
|
|
251
|
-
Formatea de manera recursiva las propiedades de un esquema JSON/YAML.
|
|
252
|
-
"""
|
|
253
|
-
output = []
|
|
254
|
-
indent_str = ' ' * indent_level
|
|
255
|
-
|
|
256
|
-
for name, details in properties.items():
|
|
257
|
-
if not isinstance(details, dict):
|
|
258
|
-
continue
|
|
259
|
-
|
|
260
|
-
description = details.get('description', '')
|
|
261
|
-
data_type = details.get('type', 'any')
|
|
262
|
-
output.append(f"{indent_str}- **`{name.lower()}`** ({data_type}): {description}")
|
|
263
|
-
# if 'pk' in details and details['pk']:
|
|
264
|
-
# output.append(f"{indent_str}- **Primary Key**: {details['pk']}")
|
|
265
|
-
|
|
266
|
-
child_indent_str = ' ' * (indent_level + 1)
|
|
267
|
-
|
|
268
|
-
# Manejo de 'oneOf' para mostrar valores constantes
|
|
269
|
-
if 'oneOf' in details:
|
|
270
|
-
for item in details['oneOf']:
|
|
271
|
-
if 'const' in item:
|
|
272
|
-
const_desc = item.get('description', '')
|
|
273
|
-
output.append(f"{child_indent_str}- `{item['const']}`: {const_desc}")
|
|
274
|
-
|
|
275
|
-
# Manejo de 'items' para arrays
|
|
276
|
-
if 'items' in details:
|
|
277
|
-
items_details = details.get('items', {})
|
|
278
|
-
if isinstance(items_details, dict):
|
|
279
|
-
item_description = items_details.get('description')
|
|
280
|
-
if item_description:
|
|
281
|
-
# Limpiamos y añadimos la descripción del item
|
|
282
|
-
cleaned_description = '\n'.join(
|
|
283
|
-
f"{line.strip()}" for line in item_description.strip().split('\n')
|
|
284
|
-
)
|
|
285
|
-
output.append(
|
|
286
|
-
f"{child_indent_str}*Descripción de los elementos del array:*\n{child_indent_str}{cleaned_description}")
|
|
287
|
-
|
|
288
|
-
if 'properties' in items_details:
|
|
289
|
-
nested_properties = self._format_json_schema(items_details['properties'], indent_level + 1)
|
|
290
|
-
output.append(nested_properties)
|
|
291
|
-
|
|
292
|
-
# Manejo de 'properties' para objetos anidados estándar
|
|
293
|
-
if 'properties' in details:
|
|
294
|
-
nested_properties = self._format_json_schema(details['properties'], indent_level + 1)
|
|
295
|
-
output.append(nested_properties)
|
|
296
|
-
|
|
297
|
-
elif 'additionalProperties' in details and 'properties' in details.get('additionalProperties', {}):
|
|
298
|
-
# Imprime un marcador de posición para la clave dinámica.
|
|
299
|
-
output.append(
|
|
300
|
-
f"{child_indent_str}- **[*]** (object): Las claves de este objeto son dinámicas (ej. un ID).")
|
|
301
|
-
# Procesa las propiedades del objeto anidado.
|
|
302
|
-
nested_properties = self._format_json_schema(details['additionalProperties']['properties'],
|
|
303
|
-
indent_level + 2)
|
|
304
|
-
output.append(nested_properties)
|
|
305
|
-
|
|
306
|
-
return '\n'.join(output)
|
|
307
192
|
|
|
308
193
|
def load_markdown_context(self, filepath: str) -> str:
|
|
309
194
|
with open(filepath, 'r', encoding='utf-8') as f:
|
|
@@ -58,6 +58,7 @@ class IAToolkit:
|
|
|
58
58
|
self._injector = Injector() # init empty injector
|
|
59
59
|
self.version = IATOOLKIT_VERSION
|
|
60
60
|
self.license = "Community Edition"
|
|
61
|
+
self.is_community = True
|
|
61
62
|
|
|
62
63
|
@classmethod
|
|
63
64
|
def get_instance(cls) -> 'IAToolkit':
|
|
@@ -321,7 +322,7 @@ class IAToolkit:
|
|
|
321
322
|
from iatoolkit.services.prompt_service import PromptService
|
|
322
323
|
from iatoolkit.services.excel_service import ExcelService
|
|
323
324
|
from iatoolkit.services.mail_service import MailService
|
|
324
|
-
from iatoolkit.services.
|
|
325
|
+
from iatoolkit.services.ingestor_service import IngestorService
|
|
325
326
|
from iatoolkit.services.profile_service import ProfileService
|
|
326
327
|
from iatoolkit.services.jwt_service import JWTService
|
|
327
328
|
from iatoolkit.services.dispatcher_service import Dispatcher
|
|
@@ -343,7 +344,7 @@ class IAToolkit:
|
|
|
343
344
|
binder.bind(PromptService, to=PromptService)
|
|
344
345
|
binder.bind(ExcelService, to=ExcelService)
|
|
345
346
|
binder.bind(MailService, to=MailService)
|
|
346
|
-
binder.bind(
|
|
347
|
+
binder.bind(IngestorService, to=IngestorService)
|
|
347
348
|
binder.bind(ProfileService, to=ProfileService)
|
|
348
349
|
binder.bind(JWTService, to=JWTService)
|
|
349
350
|
binder.bind(Dispatcher, to=Dispatcher)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
+
# Product: IAToolkit
|
|
3
|
+
#
|
|
4
|
+
# IAToolkit is open source software.
|
|
5
|
+
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
from typing import List, Optional
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FileConnector(ABC):
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def list_files(self) -> List[str]:
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
@abstractmethod
|
|
16
|
+
def get_file_content(self, file_path: str) -> bytes:
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def delete_file(self, file_path: str) -> None:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def upload_file(self, file_path: str, content: bytes, content_type: str = None) -> None:
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
def generate_presigned_url(self, file_path: str, expiration: int = 3600) -> Optional[str]:
|
|
28
|
+
return None
|
{iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/connectors/file_connector_factory.py
RENAMED
|
@@ -1,29 +1,19 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
# IAToolkit is open source software.
|
|
5
|
-
|
|
1
|
+
# ... existing code ...
|
|
2
|
+
import os
|
|
3
|
+
from typing import Dict
|
|
6
4
|
from iatoolkit.infra.connectors.file_connector import FileConnector
|
|
7
5
|
from iatoolkit.infra.connectors.local_file_connector import LocalFileConnector
|
|
8
6
|
from iatoolkit.infra.connectors.s3_connector import S3Connector
|
|
9
|
-
from iatoolkit.infra.connectors.google_drive_connector import GoogleDriveConnector
|
|
10
7
|
from iatoolkit.infra.connectors.google_cloud_storage_connector import GoogleCloudStorageConnector
|
|
11
|
-
from
|
|
12
|
-
import os
|
|
13
|
-
|
|
8
|
+
from iatoolkit.infra.connectors.google_drive_connector import GoogleDriveConnector
|
|
14
9
|
|
|
15
10
|
class FileConnectorFactory:
|
|
16
11
|
@staticmethod
|
|
17
12
|
def create(config: Dict) -> FileConnector:
|
|
18
13
|
"""
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"path": "/ruta/local", # solo para local
|
|
23
|
-
"bucket": "mi-bucket", "prefix": "datos/", "auth": {...}, # solo para S3
|
|
24
|
-
"folder_id": "xxxxxxx", # solo para Google Drive
|
|
25
|
-
"bucket": "mi-bucket", "service_account": "/ruta/service_account.json" # solo para GCS
|
|
26
|
-
}
|
|
14
|
+
Crea un conector basado en un diccionario de configuración.
|
|
15
|
+
Permite pasar credenciales explícitas en 'auth' o 'service_account_path',
|
|
16
|
+
o dejar que el conector use sus defaults.
|
|
27
17
|
"""
|
|
28
18
|
connector_type = config.get('type')
|
|
29
19
|
|
|
@@ -31,11 +21,14 @@ class FileConnectorFactory:
|
|
|
31
21
|
return LocalFileConnector(config['path'])
|
|
32
22
|
|
|
33
23
|
elif connector_type == 's3':
|
|
34
|
-
auth
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
24
|
+
# Permite inyectar auth ya resuelto, o usar defaults de entorno
|
|
25
|
+
auth = config.get('auth')
|
|
26
|
+
if not auth:
|
|
27
|
+
auth = {
|
|
28
|
+
'aws_access_key_id': os.getenv('AWS_ACCESS_KEY_ID'),
|
|
29
|
+
'aws_secret_access_key': os.getenv('AWS_SECRET_ACCESS_KEY'),
|
|
30
|
+
'region_name': os.getenv('AWS_REGION', 'us-east-1')
|
|
31
|
+
}
|
|
39
32
|
|
|
40
33
|
return S3Connector(
|
|
41
34
|
bucket=config['bucket'],
|
|
@@ -45,14 +38,16 @@ class FileConnectorFactory:
|
|
|
45
38
|
)
|
|
46
39
|
|
|
47
40
|
elif connector_type == 'gdrive':
|
|
48
|
-
return GoogleDriveConnector(
|
|
49
|
-
|
|
41
|
+
return GoogleDriveConnector(
|
|
42
|
+
folder_id=config['folder_id'],
|
|
43
|
+
service_account_path=config.get('service_account', 'service_account.json')
|
|
44
|
+
)
|
|
50
45
|
|
|
51
|
-
elif connector_type
|
|
46
|
+
elif connector_type in ['gcs', 'google_cloud_storage']:
|
|
52
47
|
return GoogleCloudStorageConnector(
|
|
53
48
|
bucket_name=config['bucket'],
|
|
54
|
-
service_account_path=config.get('
|
|
49
|
+
service_account_path=config.get('service_account_path', 'service_account.json')
|
|
55
50
|
)
|
|
56
51
|
|
|
57
52
|
else:
|
|
58
|
-
raise ValueError(f"Unknown connector type: {connector_type}")
|
|
53
|
+
raise ValueError(f"Unknown connector type: {connector_type}")
|
|
@@ -51,3 +51,17 @@ class GoogleCloudStorageConnector(FileConnector):
|
|
|
51
51
|
file_buffer = blob.download_as_bytes() # Descarga el contenido como bytes
|
|
52
52
|
|
|
53
53
|
return file_buffer
|
|
54
|
+
|
|
55
|
+
def delete_file(self, file_path: str) -> None:
|
|
56
|
+
"""
|
|
57
|
+
Elimina un archivo del bucket dado su path.
|
|
58
|
+
"""
|
|
59
|
+
blob = self.bucket.blob(file_path)
|
|
60
|
+
blob.delete()
|
|
61
|
+
|
|
62
|
+
def upload_file(self, file_path: str, content: bytes, content_type: str = None) -> None:
|
|
63
|
+
"""
|
|
64
|
+
Sube un archivo al bucket.
|
|
65
|
+
"""
|
|
66
|
+
blob = self.bucket.blob(file_path)
|
|
67
|
+
blob.upload_from_string(content, content_type=content_type)
|
{iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/connectors/google_drive_connector.py
RENAMED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
from iatoolkit.infra.connectors.file_connector import FileConnector
|
|
7
7
|
from googleapiclient.discovery import build
|
|
8
|
-
from googleapiclient.http import MediaIoBaseDownload
|
|
8
|
+
from googleapiclient.http import MediaIoBaseDownload, MediaIoBaseUpload
|
|
9
9
|
from google.oauth2.service_account import Credentials
|
|
10
10
|
import io
|
|
11
11
|
from typing import List
|
|
@@ -66,3 +66,34 @@ class GoogleDriveConnector(FileConnector):
|
|
|
66
66
|
status, done = downloader.next_chunk()
|
|
67
67
|
|
|
68
68
|
return file_buffer.getvalue()
|
|
69
|
+
|
|
70
|
+
def upload_file(self, file_path: str, content: bytes, content_type: str = None) -> None:
|
|
71
|
+
"""
|
|
72
|
+
Sube un archivo a Google Drive.
|
|
73
|
+
Nota: 'file_path' en este contexto se interpreta como el nombre del archivo,
|
|
74
|
+
ya que GDrive usa IDs para carpetas. El archivo se subirá a la carpeta configurada (self.folder_id).
|
|
75
|
+
"""
|
|
76
|
+
file_metadata = {
|
|
77
|
+
'name': file_path, # Usamos file_path como nombre
|
|
78
|
+
'parents': [self.folder_id]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
media = MediaIoBaseUpload(io.BytesIO(content), mimetype=content_type, resumable=True)
|
|
82
|
+
|
|
83
|
+
self.drive_service.files().create(
|
|
84
|
+
body=file_metadata,
|
|
85
|
+
media_body=media,
|
|
86
|
+
fields='id'
|
|
87
|
+
).execute()
|
|
88
|
+
|
|
89
|
+
def delete_file(self, file_path: str) -> None:
|
|
90
|
+
"""
|
|
91
|
+
Elimina un archivo de Google Drive.
|
|
92
|
+
Nota: 'file_path' aquí DEBE ser el ID del archivo (fileId), no su nombre.
|
|
93
|
+
"""
|
|
94
|
+
try:
|
|
95
|
+
self.drive_service.files().delete(fileId=file_path).execute()
|
|
96
|
+
except Exception:
|
|
97
|
+
# Si falla (ej: no existe), podríamos loguear o ignorar según diseño.
|
|
98
|
+
# Aquí asumimos propagación de error o manejo silencioso si no crítico.
|
|
99
|
+
pass
|
{iatoolkit-1.10.0 → iatoolkit-1.21.0}/src/iatoolkit/infra/connectors/local_file_connector.py
RENAMED
|
@@ -44,3 +44,25 @@ class LocalFileConnector(FileConnector):
|
|
|
44
44
|
except Exception as e:
|
|
45
45
|
raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
|
|
46
46
|
f"Error leyendo el archivo {file_path}: {e}")
|
|
47
|
+
|
|
48
|
+
def upload_file(self, file_path: str, content: bytes, content_type: str = None) -> None:
|
|
49
|
+
# Nota: file_path debe ser relativo al directorio raíz configurado
|
|
50
|
+
full_path = os.path.join(self.directory, file_path)
|
|
51
|
+
|
|
52
|
+
# Asegurar que el directorio destino existe
|
|
53
|
+
try:
|
|
54
|
+
os.makedirs(os.path.dirname(full_path), exist_ok=True)
|
|
55
|
+
with open(full_path, 'wb') as f:
|
|
56
|
+
f.write(content)
|
|
57
|
+
except Exception as e:
|
|
58
|
+
raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
|
|
59
|
+
f"Error escribiendo el archivo {file_path}: {e}")
|
|
60
|
+
|
|
61
|
+
def delete_file(self, file_path: str) -> None:
|
|
62
|
+
full_path = os.path.join(self.directory, file_path)
|
|
63
|
+
try:
|
|
64
|
+
if os.path.exists(full_path):
|
|
65
|
+
os.remove(full_path)
|
|
66
|
+
except Exception as e:
|
|
67
|
+
raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
|
|
68
|
+
f"Error eliminando el archivo {file_path}: {e}")
|
|
@@ -32,4 +32,30 @@ class S3Connector(FileConnector):
|
|
|
32
32
|
|
|
33
33
|
def get_file_content(self, file_path: str) -> bytes:
|
|
34
34
|
response = self.s3.get_object(Bucket=self.bucket, Key=file_path)
|
|
35
|
-
return response['Body'].read()
|
|
35
|
+
return response['Body'].read()
|
|
36
|
+
|
|
37
|
+
def delete_file(self, file_path: str) -> None:
|
|
38
|
+
self.s3.delete_object(Bucket=self.bucket, Key=file_path)
|
|
39
|
+
|
|
40
|
+
def upload_file(self, file_path: str, content: bytes, content_type: str = None) -> None:
|
|
41
|
+
# If the path doesn't start with the prefix, add it (optional, depends on your logic)'
|
|
42
|
+
# Assuming file_path is either a full path or relative to the root of the bucket for flexibility
|
|
43
|
+
full_path = file_path
|
|
44
|
+
|
|
45
|
+
extra_args = {}
|
|
46
|
+
if content_type:
|
|
47
|
+
extra_args['ContentType'] = content_type
|
|
48
|
+
|
|
49
|
+
self.s3.put_object(
|
|
50
|
+
Bucket=self.bucket,
|
|
51
|
+
Key=full_path,
|
|
52
|
+
Body=content,
|
|
53
|
+
**extra_args
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def generate_presigned_url(self, file_path: str, expiration: int = 3600) -> str:
|
|
57
|
+
return self.s3.generate_presigned_url(
|
|
58
|
+
'get_object',
|
|
59
|
+
Params={'Bucket': self.bucket, 'Key': file_path},
|
|
60
|
+
ExpiresIn=expiration
|
|
61
|
+
)
|
|
@@ -40,6 +40,13 @@ class DeepseekAdapter:
|
|
|
40
40
|
tools = kwargs.get("tools") or []
|
|
41
41
|
tool_choice = kwargs.get("tool_choice", "auto")
|
|
42
42
|
context_history = kwargs.get("context_history") or []
|
|
43
|
+
images = kwargs.get("images") or []
|
|
44
|
+
|
|
45
|
+
if images:
|
|
46
|
+
logging.warning(
|
|
47
|
+
f"[DeepseekAdapter] Images provided but DeepSeek models are not multimodal. "
|
|
48
|
+
f"Ignoring {len(images)} images."
|
|
49
|
+
)
|
|
43
50
|
|
|
44
51
|
try:
|
|
45
52
|
# 1) Build messages from history (if any)
|
|
@@ -232,6 +239,7 @@ class DeepseekAdapter:
|
|
|
232
239
|
|
|
233
240
|
# If the model produced tool calls, fills this list
|
|
234
241
|
tool_calls_out: List[ToolCall] = []
|
|
242
|
+
content_parts: List[Dict] = [] # Initialize content_parts
|
|
235
243
|
|
|
236
244
|
tool_calls = getattr(message, "tool_calls", None) or []
|
|
237
245
|
if not tool_calls:
|
|
@@ -239,6 +247,13 @@ class DeepseekAdapter:
|
|
|
239
247
|
output_text = getattr(message, "content", "") or ""
|
|
240
248
|
status = "completed"
|
|
241
249
|
|
|
250
|
+
# Fill content_parts for text response
|
|
251
|
+
if output_text:
|
|
252
|
+
content_parts.append({
|
|
253
|
+
"type": "text",
|
|
254
|
+
"text": output_text
|
|
255
|
+
})
|
|
256
|
+
|
|
242
257
|
else:
|
|
243
258
|
logging.debug(f"[DeepSeek] RAW tool_calls: {tool_calls}")
|
|
244
259
|
|
|
@@ -274,5 +289,6 @@ class DeepseekAdapter:
|
|
|
274
289
|
output_text=output_text,
|
|
275
290
|
output=tool_calls_out,
|
|
276
291
|
usage=usage,
|
|
277
|
-
reasoning_content=reasoning_content
|
|
292
|
+
reasoning_content=reasoning_content,
|
|
293
|
+
content_parts=content_parts # Pass content_parts
|
|
278
294
|
)
|