ai-microcore 5.0.0.dev8__tar.gz → 5.1.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.
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/PKG-INFO +58 -13
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/README.md +57 -12
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/__init__.py +1 -1
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/configuration.py +5 -12
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/llm/anthropic.py +11 -9
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/llm/google_genai.py +29 -2
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/llm/openai.py +22 -1
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/llm_backends.py +1 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/LICENSE +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/_env.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/_llm_functions.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/_prepare_llm_args.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/ai_func/__init__.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/ai_func/ai-func.json.j2 +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/ai_func/ai-func.pythonic.j2 +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/ai_func/ai-func.tag.j2 +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/ai_modules.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/embedding_db/__init__.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/embedding_db/chromadb.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/embedding_db/qdrant.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/file_cache.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/file_storage.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/images.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/interactive_setup.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/json_parsing.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/llm/__init__.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/llm/local_llm.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/llm/local_transformers.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/llm/shared.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/lm_client.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/logging.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/mcp.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/message_types.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/metrics.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/presets.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/python.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/templating/__init__.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/templating/jinja2.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/text2speech/elevenlabs.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/tokenizing.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/types.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/ui.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/utils.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/wrappers/__init__.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/wrappers/llm_response_wrapper.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/microcore/wrappers/prompt_wrapper.py +0 -0
- {ai_microcore-5.0.0.dev8 → ai_microcore-5.1.0}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ai-microcore
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.1.0
|
|
4
4
|
Summary: # Minimalistic Foundation for AI Applications
|
|
5
5
|
Keywords: llm,large language models,ai,similarity search,ai search,gpt,openai,framework,adapter,anthropic,google gemini,google vertex ai
|
|
6
6
|
Author-email: Vitalii Stepanenko <mail@vitaliy.in>
|
|
@@ -116,21 +116,14 @@ For the full list of available configuration options, you may also check [`micro
|
|
|
116
116
|
|
|
117
117
|
### Installing vendor-specific packages
|
|
118
118
|
For models working not via OpenAI API, you may need to install additional packages:
|
|
119
|
-
#### Anthropic Claude
|
|
119
|
+
#### Anthropic Claude
|
|
120
120
|
```bash
|
|
121
121
|
pip install anthropic
|
|
122
122
|
```
|
|
123
|
-
#### Google Gemini via AI Studio
|
|
123
|
+
#### Google Gemini via AI Studio or Vertex AI
|
|
124
124
|
```bash
|
|
125
|
-
pip install google-
|
|
125
|
+
pip install google-genai
|
|
126
126
|
```
|
|
127
|
-
#### Google Gemini via Vertex AI
|
|
128
|
-
```bash
|
|
129
|
-
pip install vertexai
|
|
130
|
-
```
|
|
131
|
-
📌Additionally for working through [Vertex AI](https://cloud.google.com/vertex-ai) you need to
|
|
132
|
-
[install the Google Cloud CLI](https://cloud.google.com/sdk/docs/install)
|
|
133
|
-
and [configure the authorization](https://cloud.google.com/sdk/docs/authorizing).
|
|
134
127
|
|
|
135
128
|
#### Local language models via Hugging Face Transformers
|
|
136
129
|
|
|
@@ -207,7 +200,7 @@ ai_response = llm('What is your model name?')
|
|
|
207
200
|
# - For chat completion models elements are treated as separate messages
|
|
208
201
|
# - For completion LLMs elements are treated as text lines
|
|
209
202
|
llm(['1+2', '='])
|
|
210
|
-
llm('1+2=', model='gpt-
|
|
203
|
+
llm('1+2=', model='gpt-5.2')
|
|
211
204
|
|
|
212
205
|
# To specify a message role, you can use dictionary or classes
|
|
213
206
|
llm(dict(role='system', content='1+2='))
|
|
@@ -313,9 +306,61 @@ Text generation using HF/Transformers model locally (example with Qwen 3 0.6B).
|
|
|
313
306
|
|
|
314
307
|
#### [Other examples](https://github.com/llm-microcore/microcore/tree/main/examples)
|
|
315
308
|
|
|
309
|
+
## 📚 Guides & Reference<a id="-guides--reference"></a>
|
|
310
|
+
|
|
311
|
+
For more detailed information, check out these articles:
|
|
312
|
+
|
|
313
|
+
- [Custom HTTP Headers](https://github.com/Nayjest/ai-microcore/blob/main/doc/features/http_headers.md)
|
|
314
|
+
- [File Cache](https://github.com/Nayjest/ai-microcore/blob/main/doc/features/file_cache.md)
|
|
315
|
+
|
|
316
316
|
## Python functions as AI tools
|
|
317
|
+
*Usage Example*:
|
|
318
|
+
```python
|
|
319
|
+
from microcore.ai_func import ai_func
|
|
320
|
+
|
|
321
|
+
@ai_func
|
|
322
|
+
def search_products(
|
|
323
|
+
query: str,
|
|
324
|
+
category: str = "all",
|
|
325
|
+
max_results: int = 10,
|
|
326
|
+
in_stock_only: bool = False
|
|
327
|
+
):
|
|
328
|
+
"""
|
|
329
|
+
Search for products in the catalog.
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
query: Search terms to find matching products
|
|
333
|
+
category: Product category to filter by (e.g., "electronics", "clothing")
|
|
334
|
+
max_results: Maximum number of results to return
|
|
335
|
+
in_stock_only: If True, only return products currently in stock
|
|
336
|
+
|
|
337
|
+
Returns:
|
|
338
|
+
List of matching products with name, price, and availability
|
|
339
|
+
"""
|
|
340
|
+
# Implementation would go here
|
|
341
|
+
pass
|
|
342
|
+
```
|
|
343
|
+
*Output*:
|
|
344
|
+
```
|
|
345
|
+
# Search for products in the catalog.
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
query: Search terms to find matching products
|
|
349
|
+
category: Product category to filter by (e.g., "electronics", "clothing")
|
|
350
|
+
max_results: Maximum number of results to return
|
|
351
|
+
in_stock_only: If True, only return products currently in stock
|
|
352
|
+
|
|
353
|
+
Returns:
|
|
354
|
+
List of matching products with name, price, and availability
|
|
355
|
+
{
|
|
356
|
+
"call": "search_products",
|
|
357
|
+
"query": <str>,
|
|
358
|
+
"category": <str> (default = "all"),
|
|
359
|
+
"max_results": <int> (default = 10),
|
|
360
|
+
"in_stock_only": <bool> (default = False)
|
|
361
|
+
}
|
|
317
362
|
|
|
318
|
-
|
|
363
|
+
```
|
|
319
364
|
|
|
320
365
|
## 🤖 AI Modules
|
|
321
366
|
**This is an experimental feature.**
|
|
@@ -81,21 +81,14 @@ For the full list of available configuration options, you may also check [`micro
|
|
|
81
81
|
|
|
82
82
|
### Installing vendor-specific packages
|
|
83
83
|
For models working not via OpenAI API, you may need to install additional packages:
|
|
84
|
-
#### Anthropic Claude
|
|
84
|
+
#### Anthropic Claude
|
|
85
85
|
```bash
|
|
86
86
|
pip install anthropic
|
|
87
87
|
```
|
|
88
|
-
#### Google Gemini via AI Studio
|
|
88
|
+
#### Google Gemini via AI Studio or Vertex AI
|
|
89
89
|
```bash
|
|
90
|
-
pip install google-
|
|
90
|
+
pip install google-genai
|
|
91
91
|
```
|
|
92
|
-
#### Google Gemini via Vertex AI
|
|
93
|
-
```bash
|
|
94
|
-
pip install vertexai
|
|
95
|
-
```
|
|
96
|
-
📌Additionally for working through [Vertex AI](https://cloud.google.com/vertex-ai) you need to
|
|
97
|
-
[install the Google Cloud CLI](https://cloud.google.com/sdk/docs/install)
|
|
98
|
-
and [configure the authorization](https://cloud.google.com/sdk/docs/authorizing).
|
|
99
92
|
|
|
100
93
|
#### Local language models via Hugging Face Transformers
|
|
101
94
|
|
|
@@ -172,7 +165,7 @@ ai_response = llm('What is your model name?')
|
|
|
172
165
|
# - For chat completion models elements are treated as separate messages
|
|
173
166
|
# - For completion LLMs elements are treated as text lines
|
|
174
167
|
llm(['1+2', '='])
|
|
175
|
-
llm('1+2=', model='gpt-
|
|
168
|
+
llm('1+2=', model='gpt-5.2')
|
|
176
169
|
|
|
177
170
|
# To specify a message role, you can use dictionary or classes
|
|
178
171
|
llm(dict(role='system', content='1+2='))
|
|
@@ -278,9 +271,61 @@ Text generation using HF/Transformers model locally (example with Qwen 3 0.6B).
|
|
|
278
271
|
|
|
279
272
|
#### [Other examples](https://github.com/llm-microcore/microcore/tree/main/examples)
|
|
280
273
|
|
|
274
|
+
## 📚 Guides & Reference<a id="-guides--reference"></a>
|
|
275
|
+
|
|
276
|
+
For more detailed information, check out these articles:
|
|
277
|
+
|
|
278
|
+
- [Custom HTTP Headers](https://github.com/Nayjest/ai-microcore/blob/main/doc/features/http_headers.md)
|
|
279
|
+
- [File Cache](https://github.com/Nayjest/ai-microcore/blob/main/doc/features/file_cache.md)
|
|
280
|
+
|
|
281
281
|
## Python functions as AI tools
|
|
282
|
+
*Usage Example*:
|
|
283
|
+
```python
|
|
284
|
+
from microcore.ai_func import ai_func
|
|
285
|
+
|
|
286
|
+
@ai_func
|
|
287
|
+
def search_products(
|
|
288
|
+
query: str,
|
|
289
|
+
category: str = "all",
|
|
290
|
+
max_results: int = 10,
|
|
291
|
+
in_stock_only: bool = False
|
|
292
|
+
):
|
|
293
|
+
"""
|
|
294
|
+
Search for products in the catalog.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
query: Search terms to find matching products
|
|
298
|
+
category: Product category to filter by (e.g., "electronics", "clothing")
|
|
299
|
+
max_results: Maximum number of results to return
|
|
300
|
+
in_stock_only: If True, only return products currently in stock
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
List of matching products with name, price, and availability
|
|
304
|
+
"""
|
|
305
|
+
# Implementation would go here
|
|
306
|
+
pass
|
|
307
|
+
```
|
|
308
|
+
*Output*:
|
|
309
|
+
```
|
|
310
|
+
# Search for products in the catalog.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
query: Search terms to find matching products
|
|
314
|
+
category: Product category to filter by (e.g., "electronics", "clothing")
|
|
315
|
+
max_results: Maximum number of results to return
|
|
316
|
+
in_stock_only: If True, only return products currently in stock
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
List of matching products with name, price, and availability
|
|
320
|
+
{
|
|
321
|
+
"call": "search_products",
|
|
322
|
+
"query": <str>,
|
|
323
|
+
"category": <str> (default = "all"),
|
|
324
|
+
"max_results": <int> (default = 10),
|
|
325
|
+
"in_stock_only": <bool> (default = False)
|
|
326
|
+
}
|
|
282
327
|
|
|
283
|
-
|
|
328
|
+
```
|
|
284
329
|
|
|
285
330
|
## 🤖 AI Modules
|
|
286
331
|
**This is an experimental feature.**
|
|
@@ -150,18 +150,6 @@ class _AnthropicEnvVars:
|
|
|
150
150
|
ANTHROPIC_API_KEY: str = from_env()
|
|
151
151
|
|
|
152
152
|
|
|
153
|
-
@dataclass
|
|
154
|
-
class _GoogleVertexAiEnvVars:
|
|
155
|
-
"""@deprecated, use _GoogleGenAiEnvVars instead"""
|
|
156
|
-
GOOGLE_VERTEX_ACCESS_TOKEN: str = from_env()
|
|
157
|
-
GOOGLE_VERTEX_PROJECT_ID: str = from_env()
|
|
158
|
-
GOOGLE_VERTEX_LOCATION: str = from_env()
|
|
159
|
-
GOOGLE_VERTEX_GCLOUD_AUTH: bool = from_env(dtype=bool)
|
|
160
|
-
|
|
161
|
-
GOOGLE_VERTEX_RESPONSE_VALIDATION: bool = from_env(dtype=bool, default=False)
|
|
162
|
-
GOOGLE_GEMINI_SAFETY_SETTINGS: dict = from_env(dtype=dict)
|
|
163
|
-
|
|
164
|
-
|
|
165
153
|
@dataclass
|
|
166
154
|
class _GoogleGenAiEnvVars:
|
|
167
155
|
# see https://docs.cloud.google.com/docs/authentication/application-default-credentials
|
|
@@ -216,6 +204,9 @@ class LLMConfig(
|
|
|
216
204
|
i. e. temperature, max_tokens, etc.
|
|
217
205
|
"""
|
|
218
206
|
|
|
207
|
+
HTTP_HEADERS: dict = from_env(dtype=dict)
|
|
208
|
+
"""Additional HTTP headers to add to LLM API requests"""
|
|
209
|
+
|
|
219
210
|
AZURE_DEPLOYMENT_ID: str = from_env()
|
|
220
211
|
|
|
221
212
|
INFERENCE_FUNC: Union[Callable, str] = from_env()
|
|
@@ -344,6 +335,8 @@ class LLMConfig(
|
|
|
344
335
|
self._resolve_model()
|
|
345
336
|
|
|
346
337
|
def _validate_local_llm(self):
|
|
338
|
+
if self.HTTP_HEADERS:
|
|
339
|
+
logging.warning("HTTP_HEADERS will be ignored for local models")
|
|
347
340
|
if self.CHAT_MODE is None:
|
|
348
341
|
logging.warning(
|
|
349
342
|
"When using local models, "
|
|
@@ -96,16 +96,18 @@ def _extract_sys_msg(prepared_messages: list[dict]) -> tuple[str, list[dict]]:
|
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
def make_llm_functions(config: Config) -> tuple[LLMFunctionType, LLMAsyncFunctionType]:
|
|
99
|
-
|
|
100
|
-
api_key
|
|
101
|
-
base_url
|
|
99
|
+
client_params = {
|
|
100
|
+
"api_key": config.LLM_API_KEY,
|
|
101
|
+
"base_url": config.LLM_API_BASE,
|
|
102
102
|
**config.INIT_PARAMS,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
103
|
+
}
|
|
104
|
+
if config.HTTP_HEADERS:
|
|
105
|
+
if "default_headers" not in client_params:
|
|
106
|
+
client_params["default_headers"] = {}
|
|
107
|
+
client_params["default_headers"].update(config.HTTP_HEADERS)
|
|
108
|
+
|
|
109
|
+
sync_client = anthropic.Anthropic(**client_params)
|
|
110
|
+
async_client = anthropic.AsyncAnthropic(**client_params)
|
|
109
111
|
|
|
110
112
|
async def allm(prompt, **kwargs):
|
|
111
113
|
args, options = _prepare_llm_arguments(config, kwargs)
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Client for Google GenAI SDK to interact with Google Gemini models.
|
|
3
|
+
"""
|
|
1
4
|
import asyncio
|
|
2
5
|
import json
|
|
3
|
-
from typing import Any, Optional
|
|
6
|
+
from typing import Any, Optional, Mapping
|
|
4
7
|
from dataclasses import dataclass
|
|
5
8
|
|
|
6
9
|
from google import genai
|
|
7
10
|
from google.genai import types
|
|
11
|
+
from google.genai.types import HttpOptions
|
|
8
12
|
from google.oauth2.service_account import Credentials
|
|
9
13
|
|
|
10
14
|
from ..configuration import Config, LLMCredentialError
|
|
@@ -59,6 +63,22 @@ def _load_service_account_info(config: Config) -> Optional[dict]:
|
|
|
59
63
|
)
|
|
60
64
|
return None
|
|
61
65
|
|
|
66
|
+
def inject_headers(headers: Mapping[str,str], params: dict) -> None:
|
|
67
|
+
"""
|
|
68
|
+
Inject extra HTTP headers into the params dictionary for Google GenAI client.
|
|
69
|
+
"""
|
|
70
|
+
if "http_options" not in params:
|
|
71
|
+
params["http_options"] = {}
|
|
72
|
+
http_options = params["http_options"]
|
|
73
|
+
if isinstance(http_options, dict):
|
|
74
|
+
if "headers" not in http_options:
|
|
75
|
+
http_options["headers"] = {}
|
|
76
|
+
http_options["headers"].update(headers)
|
|
77
|
+
elif isinstance(http_options, HttpOptions):
|
|
78
|
+
if http_options.headers is None:
|
|
79
|
+
http_options.headers = {}
|
|
80
|
+
http_options.headers.update(headers)
|
|
81
|
+
|
|
62
82
|
|
|
63
83
|
class GoogleClient(BaseAIChatClient):
|
|
64
84
|
"""
|
|
@@ -71,6 +91,9 @@ class GoogleClient(BaseAIChatClient):
|
|
|
71
91
|
super().__init__(config)
|
|
72
92
|
client_params = {**config.INIT_PARAMS}
|
|
73
93
|
|
|
94
|
+
if config.HTTP_HEADERS:
|
|
95
|
+
inject_headers(config.HTTP_HEADERS, client_params)
|
|
96
|
+
|
|
74
97
|
if config.GOOGLE_GENAI_USE_VERTEXAI is not None:
|
|
75
98
|
client_params["vertexai"] = config.GOOGLE_GENAI_USE_VERTEXAI
|
|
76
99
|
|
|
@@ -222,6 +245,10 @@ class _GenerationContext:
|
|
|
222
245
|
model_name = kwargs.pop("model", client.config.MODEL)
|
|
223
246
|
callbacks = prepare_callbacks(client.config, kwargs, set_stream=False)
|
|
224
247
|
is_image = is_image_model(model_name)
|
|
248
|
+
stream = kwargs.pop("stream", False) or (callbacks and not is_image)
|
|
249
|
+
if "extra_headers" in kwargs: # OpenAI compatible extra headers injection
|
|
250
|
+
extra_headers = kwargs.pop("extra_headers")
|
|
251
|
+
inject_headers(extra_headers, kwargs)
|
|
225
252
|
return _GenerationContext(
|
|
226
253
|
model_name=model_name,
|
|
227
254
|
save=kwargs.pop("save", True),
|
|
@@ -231,7 +258,7 @@ class _GenerationContext:
|
|
|
231
258
|
genai_client=client.genai_client,
|
|
232
259
|
config=client.config,
|
|
233
260
|
is_image_model=is_image,
|
|
234
|
-
stream=
|
|
261
|
+
stream=stream,
|
|
235
262
|
)
|
|
236
263
|
|
|
237
264
|
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OpenAI LLM client implementation.
|
|
3
|
+
"""
|
|
1
4
|
import asyncio
|
|
2
5
|
import base64
|
|
6
|
+
from typing import Any
|
|
3
7
|
|
|
4
8
|
import openai
|
|
5
9
|
from openai.types import CompletionChoice, ImagesResponse
|
|
6
10
|
|
|
7
11
|
from ..lm_client import BaseAIChatClient, BaseAsyncAIClient
|
|
8
|
-
from ..message_types import TMsgContentPart
|
|
12
|
+
from ..message_types import TMsgContentPart, TMsgContent
|
|
9
13
|
from ..configuration import Config
|
|
10
14
|
from ..llm_backends import ApiPlatform
|
|
11
15
|
from .._prepare_llm_args import prepare_prompt
|
|
@@ -111,6 +115,11 @@ class OpenAIClient(BaseAIChatClient):
|
|
|
111
115
|
"base_url": config.LLM_API_BASE,
|
|
112
116
|
**config.INIT_PARAMS,
|
|
113
117
|
}
|
|
118
|
+
if config.HTTP_HEADERS:
|
|
119
|
+
if "default_headers" not in client_params: # maybe set in INIT_PARAMS
|
|
120
|
+
client_params["default_headers"] = {}
|
|
121
|
+
client_params["default_headers"].update(config.HTTP_HEADERS)
|
|
122
|
+
|
|
114
123
|
self.oai_client = client_type(**client_params)
|
|
115
124
|
self.aio = AsyncOpenAIClient(
|
|
116
125
|
oai_connection=async_client_type(**client_params),
|
|
@@ -132,6 +141,18 @@ class OpenAIClient(BaseAIChatClient):
|
|
|
132
141
|
return image_to_oai(img)
|
|
133
142
|
return content_part
|
|
134
143
|
|
|
144
|
+
def _convert_message_content(self, message_content: TMsgContent) -> Any:
|
|
145
|
+
"""
|
|
146
|
+
Convert the message content into a format suitable for the LLM inference chat API.
|
|
147
|
+
"""
|
|
148
|
+
if isinstance(message_content, str):
|
|
149
|
+
# Prevent conversion of string content into dict(type=text, text=...)
|
|
150
|
+
# because Azure OpenAI fails with Error 400
|
|
151
|
+
# when passing "azure_search" data source like following:
|
|
152
|
+
# llm(..., extra_body={"data_sources"=[{"type": "azure_search",...}]})
|
|
153
|
+
return message_content
|
|
154
|
+
return super()._convert_message_content(message_content)
|
|
155
|
+
|
|
135
156
|
def load_models(self, **kwargs) -> dict:
|
|
136
157
|
models_iter = self.oai_client.models.list(**kwargs)
|
|
137
158
|
return {model.id: model for model in models_iter}
|
|
@@ -166,6 +166,7 @@ class ApiPlatform(SafeStrEnum):
|
|
|
166
166
|
return LLM_API_BASE_URLS.get(self.api_type(), {}).get(self)
|
|
167
167
|
|
|
168
168
|
|
|
169
|
+
# Human-readable labels for API platforms not following val.replace('_', ' ').title() pattern
|
|
169
170
|
_API_PLATFORM_CUSTOM_LABELS: dict[ApiPlatform, str] = {
|
|
170
171
|
ApiPlatform.OPENAI: "OpenAI",
|
|
171
172
|
ApiPlatform.GOOGLE_AI_STUDIO: "Google AI Studio",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|