iatoolkit 0.3.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.
Potentially problematic release.
This version of iatoolkit might be problematic. Click here for more details.
- iatoolkit/__init__.py +41 -0
- iatoolkit/base_company.py +42 -0
- iatoolkit/company_registry.py +98 -0
- iatoolkit/iatoolkit.py +405 -0
- iatoolkit/toolkit_config.py +13 -0
- iatoolkit-0.3.1.dist-info/METADATA +252 -0
- iatoolkit-0.3.1.dist-info/RECORD +28 -0
- iatoolkit-0.3.1.dist-info/WHEEL +5 -0
- iatoolkit-0.3.1.dist-info/top_level.txt +2 -0
- services/__init__.py +5 -0
- services/api_service.py +30 -0
- services/benchmark_service.py +139 -0
- services/dispatcher_service.py +312 -0
- services/document_service.py +159 -0
- services/excel_service.py +98 -0
- services/file_processor_service.py +92 -0
- services/history_service.py +45 -0
- services/jwt_service.py +91 -0
- services/load_documents_service.py +212 -0
- services/mail_service.py +62 -0
- services/profile_service.py +376 -0
- services/prompt_manager_service.py +180 -0
- services/query_service.py +332 -0
- services/search_service.py +32 -0
- services/sql_service.py +42 -0
- services/tasks_service.py +188 -0
- services/user_feedback_service.py +67 -0
- services/user_session_context_service.py +85 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: iatoolkit
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: IAToolkit
|
|
5
|
+
Author: Fernando Libedinsky
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: aiohappyeyeballs==2.4.4
|
|
10
|
+
Requires-Dist: aiohttp==3.11.9
|
|
11
|
+
Requires-Dist: aiosignal==1.3.1
|
|
12
|
+
Requires-Dist: annotated-types==0.7.0
|
|
13
|
+
Requires-Dist: anyio==4.6.2.post1
|
|
14
|
+
Requires-Dist: asgiref==3.8.1
|
|
15
|
+
Requires-Dist: async-timeout==4.0.3
|
|
16
|
+
Requires-Dist: attrs==24.3.0
|
|
17
|
+
Requires-Dist: backoff==2.2.1
|
|
18
|
+
Requires-Dist: bcrypt==4.2.1
|
|
19
|
+
Requires-Dist: beautifulsoup4==4.12.3
|
|
20
|
+
Requires-Dist: blinker==1.9.0
|
|
21
|
+
Requires-Dist: boto3==1.36.22
|
|
22
|
+
Requires-Dist: botocore==1.36.22
|
|
23
|
+
Requires-Dist: build==1.2.2.post1
|
|
24
|
+
Requires-Dist: cachelib==0.13.0
|
|
25
|
+
Requires-Dist: cachetools==5.5.0
|
|
26
|
+
Requires-Dist: certifi==2024.12.14
|
|
27
|
+
Requires-Dist: cffi==1.17.1
|
|
28
|
+
Requires-Dist: charset-normalizer==3.4.0
|
|
29
|
+
Requires-Dist: click==8.1.8
|
|
30
|
+
Requires-Dist: coloredlogs==15.0.1
|
|
31
|
+
Requires-Dist: contourpy==1.3.3
|
|
32
|
+
Requires-Dist: coverage==7.6.10
|
|
33
|
+
Requires-Dist: cryptography==44.0.3
|
|
34
|
+
Requires-Dist: cycler==0.12.1
|
|
35
|
+
Requires-Dist: dataclasses-json==0.6.7
|
|
36
|
+
Requires-Dist: Deprecated==1.2.15
|
|
37
|
+
Requires-Dist: distro==1.9.0
|
|
38
|
+
Requires-Dist: durationpy==0.9
|
|
39
|
+
Requires-Dist: ecs-logging==2.2.0
|
|
40
|
+
Requires-Dist: elastic-apm==6.23.0
|
|
41
|
+
Requires-Dist: et_xmlfile==2.0.0
|
|
42
|
+
Requires-Dist: exceptiongroup==1.2.2
|
|
43
|
+
Requires-Dist: fastapi==0.115.6
|
|
44
|
+
Requires-Dist: filelock==3.16.1
|
|
45
|
+
Requires-Dist: Flask==3.1.0
|
|
46
|
+
Requires-Dist: Flask-Bcrypt==1.0.1
|
|
47
|
+
Requires-Dist: flask-cors==6.0.0
|
|
48
|
+
Requires-Dist: Flask-Injector==0.15.0
|
|
49
|
+
Requires-Dist: Flask-Session==0.8.0
|
|
50
|
+
Requires-Dist: flatbuffers==24.3.25
|
|
51
|
+
Requires-Dist: fonttools==4.59.2
|
|
52
|
+
Requires-Dist: frozenlist==1.5.0
|
|
53
|
+
Requires-Dist: fsspec==2024.10.0
|
|
54
|
+
Requires-Dist: google-ai-generativelanguage==0.6.15
|
|
55
|
+
Requires-Dist: google-api-core==2.24.1
|
|
56
|
+
Requires-Dist: google-api-python-client==2.161.0
|
|
57
|
+
Requires-Dist: google-auth==2.37.0
|
|
58
|
+
Requires-Dist: google-auth-httplib2==0.2.0
|
|
59
|
+
Requires-Dist: google-auth-oauthlib==1.2.1
|
|
60
|
+
Requires-Dist: google-cloud-core==2.4.1
|
|
61
|
+
Requires-Dist: google-cloud-storage==3.0.0
|
|
62
|
+
Requires-Dist: google-crc32c==1.6.0
|
|
63
|
+
Requires-Dist: google-generativeai==0.8.5
|
|
64
|
+
Requires-Dist: google-resumable-media==2.7.2
|
|
65
|
+
Requires-Dist: googleapis-common-protos==1.66.0
|
|
66
|
+
Requires-Dist: grpcio==1.74.0
|
|
67
|
+
Requires-Dist: grpcio-status==1.71.2
|
|
68
|
+
Requires-Dist: gunicorn==23.0.0
|
|
69
|
+
Requires-Dist: h11==0.14.0
|
|
70
|
+
Requires-Dist: httpcore==1.0.7
|
|
71
|
+
Requires-Dist: httplib2==0.22.0
|
|
72
|
+
Requires-Dist: httptools==0.6.4
|
|
73
|
+
Requires-Dist: httpx==0.28.0
|
|
74
|
+
Requires-Dist: httpx-sse==0.4.0
|
|
75
|
+
Requires-Dist: huggingface-hub==0.31.4
|
|
76
|
+
Requires-Dist: humanfriendly==10.0
|
|
77
|
+
Requires-Dist: idna==3.10
|
|
78
|
+
Requires-Dist: importlib_metadata==8.5.0
|
|
79
|
+
Requires-Dist: importlib_resources==6.4.5
|
|
80
|
+
Requires-Dist: iniconfig==2.0.0
|
|
81
|
+
Requires-Dist: injector==0.22.0
|
|
82
|
+
Requires-Dist: itsdangerous==2.2.0
|
|
83
|
+
Requires-Dist: Jinja2==3.1.5
|
|
84
|
+
Requires-Dist: jiter==0.8.0
|
|
85
|
+
Requires-Dist: jmespath==1.0.1
|
|
86
|
+
Requires-Dist: joblib==1.4.2
|
|
87
|
+
Requires-Dist: jsonpatch==1.33
|
|
88
|
+
Requires-Dist: jsonpointer==3.0.0
|
|
89
|
+
Requires-Dist: kiwisolver==1.4.9
|
|
90
|
+
Requires-Dist: kubernetes==31.0.0
|
|
91
|
+
Requires-Dist: langchain==0.3.19
|
|
92
|
+
Requires-Dist: langchain-core==0.3.35
|
|
93
|
+
Requires-Dist: langchain-text-splitters==0.3.6
|
|
94
|
+
Requires-Dist: langsmith==0.3.8
|
|
95
|
+
Requires-Dist: lxml==5.3.0
|
|
96
|
+
Requires-Dist: markdown-it-py==3.0.0
|
|
97
|
+
Requires-Dist: markdown2==2.5.3
|
|
98
|
+
Requires-Dist: MarkupSafe==3.0.2
|
|
99
|
+
Requires-Dist: marshmallow==3.23.1
|
|
100
|
+
Requires-Dist: matplotlib==3.10.6
|
|
101
|
+
Requires-Dist: mdurl==0.1.2
|
|
102
|
+
Requires-Dist: mmh3==5.0.1
|
|
103
|
+
Requires-Dist: monotonic==1.6
|
|
104
|
+
Requires-Dist: mpmath==1.3.0
|
|
105
|
+
Requires-Dist: msgspec==0.19.0
|
|
106
|
+
Requires-Dist: multidict==6.1.0
|
|
107
|
+
Requires-Dist: mypy-extensions==1.0.0
|
|
108
|
+
Requires-Dist: narwhals==2.3.0
|
|
109
|
+
Requires-Dist: networkx==3.4.2
|
|
110
|
+
Requires-Dist: numpy==2.2.3
|
|
111
|
+
Requires-Dist: oauth2client==4.1.3
|
|
112
|
+
Requires-Dist: oauthlib==3.2.2
|
|
113
|
+
Requires-Dist: onnxruntime==1.19.2
|
|
114
|
+
Requires-Dist: openai==1.79.0
|
|
115
|
+
Requires-Dist: openpyxl==3.1.5
|
|
116
|
+
Requires-Dist: opentelemetry-api==1.28.2
|
|
117
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-common==1.28.2
|
|
118
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc==1.28.2
|
|
119
|
+
Requires-Dist: opentelemetry-instrumentation==0.49b2
|
|
120
|
+
Requires-Dist: opentelemetry-instrumentation-asgi==0.49b2
|
|
121
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi==0.49b2
|
|
122
|
+
Requires-Dist: opentelemetry-proto==1.28.2
|
|
123
|
+
Requires-Dist: opentelemetry-sdk==1.28.2
|
|
124
|
+
Requires-Dist: opentelemetry-semantic-conventions==0.49b2
|
|
125
|
+
Requires-Dist: opentelemetry-util-http==0.49b2
|
|
126
|
+
Requires-Dist: orjson==3.10.12
|
|
127
|
+
Requires-Dist: overrides==7.7.0
|
|
128
|
+
Requires-Dist: packaging==24.2
|
|
129
|
+
Requires-Dist: pandas==2.3.1
|
|
130
|
+
Requires-Dist: pgvector==0.3.6
|
|
131
|
+
Requires-Dist: pillow==11.0.0
|
|
132
|
+
Requires-Dist: plotly==6.3.0
|
|
133
|
+
Requires-Dist: pluggy==1.5.0
|
|
134
|
+
Requires-Dist: posthog==3.7.4
|
|
135
|
+
Requires-Dist: propcache==0.2.1
|
|
136
|
+
Requires-Dist: proto-plus==1.26.0
|
|
137
|
+
Requires-Dist: protobuf==5.29.1
|
|
138
|
+
Requires-Dist: psutil==7.0.0
|
|
139
|
+
Requires-Dist: psycopg2-binary==2.9.10
|
|
140
|
+
Requires-Dist: pyarrow==21.0.0
|
|
141
|
+
Requires-Dist: pyasn1==0.6.1
|
|
142
|
+
Requires-Dist: pyasn1_modules==0.4.1
|
|
143
|
+
Requires-Dist: pycparser==2.22
|
|
144
|
+
Requires-Dist: pydantic==2.10.2
|
|
145
|
+
Requires-Dist: pydantic-settings==2.6.1
|
|
146
|
+
Requires-Dist: pydantic_core==2.27.1
|
|
147
|
+
Requires-Dist: PyDrive==1.3.1
|
|
148
|
+
Requires-Dist: Pygments==2.18.0
|
|
149
|
+
Requires-Dist: PyJWT==2.10.1
|
|
150
|
+
Requires-Dist: PyMuPDF==1.25.0
|
|
151
|
+
Requires-Dist: pyparsing==3.2.1
|
|
152
|
+
Requires-Dist: pypdf==5.1.0
|
|
153
|
+
Requires-Dist: PyPika==0.48.9
|
|
154
|
+
Requires-Dist: pyproject_hooks==1.2.0
|
|
155
|
+
Requires-Dist: pytesseract==0.3.13
|
|
156
|
+
Requires-Dist: pytest==8.3.4
|
|
157
|
+
Requires-Dist: pytest-cov==5.0.0
|
|
158
|
+
Requires-Dist: pytest-mock==3.14.0
|
|
159
|
+
Requires-Dist: python-dateutil==2.9.0.post0
|
|
160
|
+
Requires-Dist: python-docx==1.1.2
|
|
161
|
+
Requires-Dist: python-dotenv==1.0.1
|
|
162
|
+
Requires-Dist: pytz==2025.2
|
|
163
|
+
Requires-Dist: PyYAML==6.0.2
|
|
164
|
+
Requires-Dist: redis==5.2.1
|
|
165
|
+
Requires-Dist: regex==2024.11.6
|
|
166
|
+
Requires-Dist: requests==2.32.3
|
|
167
|
+
Requires-Dist: requests-oauthlib==2.0.0
|
|
168
|
+
Requires-Dist: requests-toolbelt==1.0.0
|
|
169
|
+
Requires-Dist: rich==13.9.4
|
|
170
|
+
Requires-Dist: rsa==4.9
|
|
171
|
+
Requires-Dist: s3transfer==0.11.2
|
|
172
|
+
Requires-Dist: safetensors==0.5.2
|
|
173
|
+
Requires-Dist: scikit-learn==1.7.1
|
|
174
|
+
Requires-Dist: scipy==1.15.1
|
|
175
|
+
Requires-Dist: seaborn==0.13.2
|
|
176
|
+
Requires-Dist: setuptools==75.8.0
|
|
177
|
+
Requires-Dist: shellingham==1.5.4
|
|
178
|
+
Requires-Dist: sib-api-v3-sdk==7.6.0
|
|
179
|
+
Requires-Dist: six==1.17.0
|
|
180
|
+
Requires-Dist: sniffio==1.3.1
|
|
181
|
+
Requires-Dist: soupsieve==2.6
|
|
182
|
+
Requires-Dist: SQLAlchemy==2.0.36
|
|
183
|
+
Requires-Dist: starlette==0.41.3
|
|
184
|
+
Requires-Dist: sympy==1.13.1
|
|
185
|
+
Requires-Dist: tenacity==9.0.0
|
|
186
|
+
Requires-Dist: threadpoolctl==3.5.0
|
|
187
|
+
Requires-Dist: tiktoken==0.8.0
|
|
188
|
+
Requires-Dist: tokenizers==0.21.0
|
|
189
|
+
Requires-Dist: tomli==2.2.1
|
|
190
|
+
Requires-Dist: tqdm==4.67.1
|
|
191
|
+
Requires-Dist: typer==0.15.1
|
|
192
|
+
Requires-Dist: typing-inspect==0.9.0
|
|
193
|
+
Requires-Dist: typing_extensions==4.12.2
|
|
194
|
+
Requires-Dist: tzdata==2025.2
|
|
195
|
+
Requires-Dist: uritemplate==4.1.1
|
|
196
|
+
Requires-Dist: urllib3==2.3.0
|
|
197
|
+
Requires-Dist: uvicorn==0.32.1
|
|
198
|
+
Requires-Dist: uvloop==0.21.0
|
|
199
|
+
Requires-Dist: watchfiles==1.0.0
|
|
200
|
+
Requires-Dist: websocket-client==1.8.0
|
|
201
|
+
Requires-Dist: websockets==14.1
|
|
202
|
+
Requires-Dist: Werkzeug==3.1.3
|
|
203
|
+
Requires-Dist: whitenoise==6.8.2
|
|
204
|
+
Requires-Dist: wikipedia==1.4.0
|
|
205
|
+
Requires-Dist: wrapt==1.17.0
|
|
206
|
+
Requires-Dist: yarl==1.18.3
|
|
207
|
+
Requires-Dist: zipp==3.21.0
|
|
208
|
+
Requires-Dist: zstandard==0.23.0
|
|
209
|
+
|
|
210
|
+
# iatoolkit
|
|
211
|
+
|
|
212
|
+
IAToolkit is a comprehensive, open-source framework designed for building enterprise-grade
|
|
213
|
+
AI chatbots and conversational applications.
|
|
214
|
+
Built on Flask with dependency injection, it provides a robust foundation for scalable AI solutions.
|
|
215
|
+
|
|
216
|
+
## 🚀 Key Features
|
|
217
|
+
- **Universal LLM Integration**: OpenAI GPT, Google Gemini
|
|
218
|
+
- **Template System**: Jinja2-powered prompt templates with variables
|
|
219
|
+
- **Context Management**: Maintain conversation context across sessions
|
|
220
|
+
|
|
221
|
+
### 🔒 **Enterprise Security**
|
|
222
|
+
- **JWT Authentication**: Secure token-based authentication
|
|
223
|
+
- **Session Management**: Redis-backed secure sessions
|
|
224
|
+
- **CORS Configuration**: Flexible cross-origin resource sharing
|
|
225
|
+
|
|
226
|
+
### 🛠 **Function Calling & Tools**
|
|
227
|
+
- **Native Function Calls**: Direct integration with LLM function calling
|
|
228
|
+
- **Custom Tools**: Build and register custom tools for your chatbot
|
|
229
|
+
- **SQL Query Generation**: Natural language to SQL conversion
|
|
230
|
+
- **API Integrations**: Connect to external services and APIs
|
|
231
|
+
|
|
232
|
+
### 🗄 **Database & Storage**
|
|
233
|
+
- **Multi-Database Support**: PostgreSQL, MySQL, SQLite via SQLAlchemy
|
|
234
|
+
- **Vector Store Integration**: Semantic search and retrieval
|
|
235
|
+
- **Document Processing**: PDF, Word, Excel, and text file handling
|
|
236
|
+
|
|
237
|
+
### 📊 **Analytics & Monitoring**
|
|
238
|
+
- **Query Logging**: Track all LLM interactions
|
|
239
|
+
- **Performance Metrics**: Response times, token usage, costs
|
|
240
|
+
- **Benchmarking**: Compare model performance
|
|
241
|
+
- **Task Management**: Async task processing with status tracking
|
|
242
|
+
|
|
243
|
+
### 🔧 **Developer Experience**
|
|
244
|
+
- **Dependency Injection**: Clean, testable architecture
|
|
245
|
+
- **CLI Tools**: Command-line interface for common tasks
|
|
246
|
+
- **Hot Reloading**: Development-friendly configuration
|
|
247
|
+
- **Comprehensive Logging**: Debug and monitor easily
|
|
248
|
+
|
|
249
|
+
## License
|
|
250
|
+
MIT License
|
|
251
|
+
|
|
252
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
iatoolkit/__init__.py,sha256=Yu9XbQmEjs0gA1HBnqiaORL7HUfoKuEElUIs8scg4IQ,1125
|
|
2
|
+
iatoolkit/base_company.py,sha256=VWfpNofFlmgHQQK8BCw2KSOPLd2DM9eA68lGQ3SDE7M,1639
|
|
3
|
+
iatoolkit/company_registry.py,sha256=saOf5JxsEtvAs-JqkNp-UfOIQvtVCXyujvv6G5_zi5k,3332
|
|
4
|
+
iatoolkit/iatoolkit.py,sha256=YX5Oh-WWBKX0DDrzeOeaNoBrPLm0O7t4ttntYC_rk-8,15186
|
|
5
|
+
iatoolkit/toolkit_config.py,sha256=y4y6DV_HvHbEHCKC3v5FtX9zZyuYR5qOoULPNuiNfXI,492
|
|
6
|
+
services/__init__.py,sha256=fSvSfIcPW1dHwTBY1hQ5dBEhaoorzk_GzR4G46gD8tY,173
|
|
7
|
+
services/api_service.py,sha256=VTM5OfKF7-eCT-dpl46ZnZ3ptbTxLUDH2IxnbS4T3jA,1113
|
|
8
|
+
services/benchmark_service.py,sha256=g9JVrmAqIe_iI0D1DwdQ6DJ2_FJRCTndarESNSVfhbw,5907
|
|
9
|
+
services/dispatcher_service.py,sha256=iNu_gUZS_AgbwmCxtLBk0A33-jxsnMGYAKI5ScaJ-yE,13207
|
|
10
|
+
services/document_service.py,sha256=sm5QtbrKs2dF9hpLuSLMB-IMWYNBD7yWHv3rd80aD0o,5960
|
|
11
|
+
services/excel_service.py,sha256=wE9Udbyb96kGRSnZZ6KM2mbE484rKjTEhta9GKKpy-8,3630
|
|
12
|
+
services/file_processor_service.py,sha256=82UArWtwpr94CAMkkoRP0_nPtoqItymdKSIABS0Xkxw,2943
|
|
13
|
+
services/history_service.py,sha256=dl-D7qgdnzpY9QhjuxJokBYZZ1AF0y59HbRzwpPet58,1654
|
|
14
|
+
services/jwt_service.py,sha256=dC45Sn6FyzdzRiQJnzgkjN3Hy21V1imRxB0hTyWRvlA,3979
|
|
15
|
+
services/load_documents_service.py,sha256=_-OTUih8Zk0m4dHqAhkE7kAwU2mbz_QoMrOKnrq7ZWs,8821
|
|
16
|
+
services/mail_service.py,sha256=ystFit1LuYUC4ekYYebyiy1rqYQmxeL6K8h58MxEkOY,2233
|
|
17
|
+
services/profile_service.py,sha256=z1dSX45HDv8VJE4w8-ucpb3kBpE2fkyOdtgnrHc9vuE,17918
|
|
18
|
+
services/prompt_manager_service.py,sha256=nnr_iNIFeJzOY_1fbuu5-reyJS04RvGx5JW_d3YFUbk,7966
|
|
19
|
+
services/query_service.py,sha256=Fx_P1WcuoAp_TyocN5LGlv_hc_03ImzU5QdAIqQg0ek,15591
|
|
20
|
+
services/search_service.py,sha256=oJD6WRXCJBD7WUVHWWKxexRkhR8nQSrFtcPV3pFO2KQ,1153
|
|
21
|
+
services/sql_service.py,sha256=H7CIPpXTcxLXLojD2fBFr_mIAD0PW1vEJhKHLfJi4Hk,1418
|
|
22
|
+
services/tasks_service.py,sha256=hHJDlcsSOPtEleD6_Vv3pocfxWNmthIhmZSdnoWFpEM,6861
|
|
23
|
+
services/user_feedback_service.py,sha256=YtCndRBekDEWYEbac431Ksn2gMO5iBrI3WqKK0xtShE,2513
|
|
24
|
+
services/user_session_context_service.py,sha256=5qn7fqpuiU8KgMpU4M5-iRUsETumz1raBw-EeZLuE1A,3868
|
|
25
|
+
iatoolkit-0.3.1.dist-info/METADATA,sha256=fhcbOmNc0NQoNP0HA_QpNc0Y7VIqgPfLWV14fz7e_IQ,8801
|
|
26
|
+
iatoolkit-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
27
|
+
iatoolkit-0.3.1.dist-info/top_level.txt,sha256=dqlBbmgo9okD9d_WMR9uYzdup7Rxgj26yFF85jRGeu4,19
|
|
28
|
+
iatoolkit-0.3.1.dist-info/RECORD,,
|
services/__init__.py
ADDED
services/api_service.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
+
# Producto: IAToolkit
|
|
3
|
+
# Todos los derechos reservados.
|
|
4
|
+
# En trámite de registro en el Registro de Propiedad Intelectual de Chile.
|
|
5
|
+
|
|
6
|
+
from infra.call_service import CallServiceClient
|
|
7
|
+
from injector import inject
|
|
8
|
+
from common.exceptions import IAToolkitException
|
|
9
|
+
import json
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ApiService:
|
|
13
|
+
@inject
|
|
14
|
+
def __init__(self, call_service: CallServiceClient):
|
|
15
|
+
self.call_service = call_service
|
|
16
|
+
|
|
17
|
+
def call_api(self, endpoint: str, method: str, **kwargs):
|
|
18
|
+
if method == 'get':
|
|
19
|
+
response, status_code = self.call_service.get(endpoint)
|
|
20
|
+
elif method == 'post':
|
|
21
|
+
response, status_code = self.call_service.post(endpoint=endpoint, json_dict=kwargs)
|
|
22
|
+
else:
|
|
23
|
+
raise IAToolkitException(IAToolkitException.ErrorType.INVALID_PARAMETER,
|
|
24
|
+
f'API error, {method} not supported')
|
|
25
|
+
|
|
26
|
+
if status_code != 200:
|
|
27
|
+
raise IAToolkitException(IAToolkitException.ErrorType.CALL_ERROR,
|
|
28
|
+
f'API {endpoint} error: {status_code}')
|
|
29
|
+
|
|
30
|
+
return json.dumps(response)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
+
# Producto: IAToolkit
|
|
3
|
+
# Todos los derechos reservados.
|
|
4
|
+
# En trámite de registro en el Registro de Propiedad Intelectual de Chile.
|
|
5
|
+
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import time
|
|
8
|
+
import logging
|
|
9
|
+
from injector import inject
|
|
10
|
+
from services.query_service import QueryService
|
|
11
|
+
from repositories.profile_repo import ProfileRepo
|
|
12
|
+
from common.exceptions import IAToolkitException
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class BenchmarkService:
|
|
16
|
+
@inject
|
|
17
|
+
def __init__(self, query_service: QueryService, profile_repo: ProfileRepo):
|
|
18
|
+
self.query_service = query_service
|
|
19
|
+
self.profile_repo = profile_repo
|
|
20
|
+
|
|
21
|
+
def _update_results_row(self, df: pd.DataFrame, index: int,
|
|
22
|
+
status: str,
|
|
23
|
+
context_time: float,
|
|
24
|
+
gpt_time: float,
|
|
25
|
+
answer: str,
|
|
26
|
+
error_msg: str,
|
|
27
|
+
query_id: int,
|
|
28
|
+
stats: dict):
|
|
29
|
+
df.at[index, 'status'] = status
|
|
30
|
+
df.at[index, 'context_time'] = round(context_time, 2)
|
|
31
|
+
df.at[index, 'gpt_time'] = round(gpt_time, 2)
|
|
32
|
+
df.at[index, 'answer'] = answer
|
|
33
|
+
df.at[index, 'error_message'] = error_msg[:512]
|
|
34
|
+
df.at[index, 'query_id'] = query_id
|
|
35
|
+
df.at[index, 'in_tokens'] = stats.get('input_tokens', 0)
|
|
36
|
+
df.at[index, 'out_tokens'] = stats.get('output_tokens', 0)
|
|
37
|
+
df.at[index, 'retry'] = stats.get('sql_retry_count', 0)
|
|
38
|
+
|
|
39
|
+
def run(self, company_short_name: str, file_path: str):
|
|
40
|
+
if not file_path.endswith('.xlsx'):
|
|
41
|
+
raise IAToolkitException(IAToolkitException.ErrorType.INVALID_PARAMETER,
|
|
42
|
+
f"solo se leer archivos .xlsx")
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
df = pd.read_excel(file_path, keep_default_na=False)
|
|
46
|
+
except FileNotFoundError:
|
|
47
|
+
raise IAToolkitException(IAToolkitException.ErrorType.INVALID_NAME,
|
|
48
|
+
f"El archivo no fue encontrado en: {file_path}")
|
|
49
|
+
|
|
50
|
+
required_columns = ['username', 'client_identity', 'prompt_name', 'question', 'model']
|
|
51
|
+
if not all(col in df.columns for col in required_columns):
|
|
52
|
+
raise IAToolkitException(IAToolkitException.ErrorType.INVALID_PARAMETER,
|
|
53
|
+
f"La planilla debe contener las columnas: {required_columns}")
|
|
54
|
+
|
|
55
|
+
# Añadir columnas para los resultados
|
|
56
|
+
df['status'] = 'pending'
|
|
57
|
+
df['context_time'] = 0.0
|
|
58
|
+
df['gpt_time'] = 0.0
|
|
59
|
+
df['answer'] = ''
|
|
60
|
+
df['error_message'] = ''
|
|
61
|
+
df['query_id'] = 0
|
|
62
|
+
df['in_tokens'] = 0
|
|
63
|
+
df['out_tokens'] = 0
|
|
64
|
+
df['retry'] = 0
|
|
65
|
+
|
|
66
|
+
company = self.profile_repo.get_company_by_short_name(company_short_name)
|
|
67
|
+
if not company:
|
|
68
|
+
raise IAToolkitException(IAToolkitException.ErrorType.CONFIG_ERROR, "Compañía 'maxxa' no encontrada.")
|
|
69
|
+
|
|
70
|
+
total_rows = len(df)
|
|
71
|
+
logging.info(f"Iniciando benchmark para {total_rows} casos de prueba desde el archivo: {file_path}")
|
|
72
|
+
|
|
73
|
+
for index, row in df.iterrows():
|
|
74
|
+
status = 'OK'
|
|
75
|
+
error_msg = ''
|
|
76
|
+
answer = ''
|
|
77
|
+
stats = {}
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
username = str(row['username'])
|
|
81
|
+
client_identity = str(row['client_identity'])
|
|
82
|
+
prompt_name = str(row['prompt_name'])
|
|
83
|
+
question = str(row['question'])
|
|
84
|
+
model = str(row['model'])
|
|
85
|
+
|
|
86
|
+
logging.info(
|
|
87
|
+
f"*** Procesando caso {index + 1}/{total_rows}: client_rut='{client_identity}', prompt='{prompt_name}'")
|
|
88
|
+
|
|
89
|
+
# 1. init context with user executing the test
|
|
90
|
+
start_time = time.time()
|
|
91
|
+
self.query_service.llm_init_context(company.short_name,
|
|
92
|
+
external_user_id=username,
|
|
93
|
+
model=model)
|
|
94
|
+
context_time = time.time() - start_time
|
|
95
|
+
|
|
96
|
+
# 2. prepare client data.
|
|
97
|
+
client_data = {'client_identity': client_identity}
|
|
98
|
+
|
|
99
|
+
# 3. execute the query
|
|
100
|
+
start_time = time.time()
|
|
101
|
+
response = self.query_service.llm_query(
|
|
102
|
+
company_short_name=company.short_name,
|
|
103
|
+
prompt_name=prompt_name,
|
|
104
|
+
question=question,
|
|
105
|
+
external_user_id=username,
|
|
106
|
+
client_data=client_data
|
|
107
|
+
)
|
|
108
|
+
gpt_time = time.time() - start_time
|
|
109
|
+
|
|
110
|
+
# 4. process the response
|
|
111
|
+
if response.get('error') or not response.get('valid_response'):
|
|
112
|
+
status = 'FAILED'
|
|
113
|
+
error_msg = response.get('error_message', 'Error desconocido en la respuesta.')
|
|
114
|
+
else:
|
|
115
|
+
answer = response.get('answer', '')
|
|
116
|
+
stats = response.get('stats', {})
|
|
117
|
+
|
|
118
|
+
query_id = response.get('query_id', 0)
|
|
119
|
+
|
|
120
|
+
except Exception as e:
|
|
121
|
+
status = 'FAILED'
|
|
122
|
+
error_msg = f"Excepción durante la ejecución: {type(e).__name__} - {str(e)}"
|
|
123
|
+
logging.error(f"Fallo en el caso {index + 1}: {error_msg}")
|
|
124
|
+
|
|
125
|
+
finally:
|
|
126
|
+
self._update_results_row(df, index,
|
|
127
|
+
status=status,
|
|
128
|
+
context_time=context_time,
|
|
129
|
+
gpt_time=gpt_time,
|
|
130
|
+
answer=answer,
|
|
131
|
+
error_msg=error_msg,
|
|
132
|
+
stats=stats,
|
|
133
|
+
query_id=query_id)
|
|
134
|
+
|
|
135
|
+
output_filename = file_path.replace('.xlsx', '_results.xlsx')
|
|
136
|
+
df.to_excel(output_filename, index=False)
|
|
137
|
+
logging.info(f"Benchmark finalizado. Resultados guardados en: {output_filename}")
|
|
138
|
+
|
|
139
|
+
return output_filename
|