ai-microcore 4.0.0.dev4__tar.gz → 4.0.0.dev5__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-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/PKG-INFO +1 -1
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/__init__.py +1 -1
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/_env.py +3 -2
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/_llm_functions.py +66 -5
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/text2speech/elevenlabs.py +30 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/types.py +3 -2
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/wrappers/llm_response_wrapper.py +20 -2
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/LICENSE +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/README.md +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/_prepare_llm_args.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/ai_func/__init__.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/ai_func/ai-func.json.j2 +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/ai_func/ai-func.pythonic.j2 +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/ai_modules.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/configuration.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/embedding_db/__init__.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/embedding_db/chromadb.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/file_storage.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/json_parsing.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/llm/__init__.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/llm/_openai_llm_v0.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/llm/_openai_llm_v1.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/llm/anthropic.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/llm/google_genai.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/llm/google_vertex_ai.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/llm/local_llm.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/llm/local_transformers.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/llm/openai_llm.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/llm/shared.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/logging.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/message_types.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/metrics.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/python.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/templating/__init__.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/templating/jinja2.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/tokenizing.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/ui.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/utils.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/wrappers/__init__.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/wrappers/prompt_wrapper.py +0 -0
- {ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ai-microcore
|
|
3
|
-
Version: 4.0.0.
|
|
3
|
+
Version: 4.0.0.dev5
|
|
4
4
|
Summary: # Minimalistic Foundation for AI Applications
|
|
5
5
|
Keywords: llm,large language models,ai,similarity search,ai search,gpt,openai
|
|
6
6
|
Author-email: Vitalii Stepanenko <mail@vitalii.in>
|
|
@@ -14,6 +14,7 @@ from .llm.local_llm import make_llm_functions as make_local_llm_functions
|
|
|
14
14
|
|
|
15
15
|
if TYPE_CHECKING:
|
|
16
16
|
from .wrappers.llm_response_wrapper import LLMResponse # noqa: F401
|
|
17
|
+
from transformers import PreTrainedModel, PreTrainedTokenizer # noqa: F401
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
@dataclass
|
|
@@ -26,10 +27,10 @@ class Env:
|
|
|
26
27
|
llm_before_handlers: list[callable] = field(default_factory=list)
|
|
27
28
|
llm_after_handlers: list[callable] = field(default_factory=list)
|
|
28
29
|
texts: AbstractEmbeddingDB = None
|
|
29
|
-
model: "
|
|
30
|
+
model: "PreTrainedModel" = field(
|
|
30
31
|
default=None, init=False, repr=False
|
|
31
32
|
) # noqa
|
|
32
|
-
tokenizer: "
|
|
33
|
+
tokenizer: "PreTrainedTokenizer" = field( # noqa
|
|
33
34
|
default=None, init=False, repr=False
|
|
34
35
|
)
|
|
35
36
|
|
|
@@ -1,17 +1,27 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from datetime import datetime
|
|
2
3
|
|
|
3
4
|
from .utils import run_parallel
|
|
4
|
-
from .wrappers.llm_response_wrapper import LLMResponse
|
|
5
|
+
from .wrappers.llm_response_wrapper import LLMResponse, DictFromLLMResponse
|
|
5
6
|
from .types import TPrompt
|
|
6
7
|
from ._env import env
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
def llm(
|
|
10
|
+
def llm(
|
|
11
|
+
prompt: TPrompt,
|
|
12
|
+
retries: int = 0,
|
|
13
|
+
parse_json: bool | dict = False,
|
|
14
|
+
**kwargs
|
|
15
|
+
) -> str | LLMResponse:
|
|
10
16
|
"""
|
|
11
17
|
Request Large Language Model synchronously
|
|
12
18
|
|
|
13
19
|
Args:
|
|
14
20
|
prompt (str | Msg | dict | list[str | Msg | dict]): Text to send to LLM
|
|
21
|
+
retries (int): Number of retries in case of error
|
|
22
|
+
parse_json (bool|dict):
|
|
23
|
+
If True, parses response as JSON,
|
|
24
|
+
alternatively non-empty dict can be used as parse_json arguments
|
|
15
25
|
**kwargs (dict): Parameters supported by the LLM API
|
|
16
26
|
|
|
17
27
|
See parameters supported by the OpenAI:
|
|
@@ -40,7 +50,18 @@ def llm(prompt: TPrompt, **kwargs) -> str | LLMResponse:
|
|
|
40
50
|
"""
|
|
41
51
|
[h(prompt, **kwargs) for h in env().llm_before_handlers]
|
|
42
52
|
start = datetime.now()
|
|
43
|
-
|
|
53
|
+
tries = retries + 1
|
|
54
|
+
while tries > 0:
|
|
55
|
+
try:
|
|
56
|
+
tries -= 1
|
|
57
|
+
response = env().llm_function(prompt, **kwargs)
|
|
58
|
+
break
|
|
59
|
+
except Exception as e:
|
|
60
|
+
if tries == 0:
|
|
61
|
+
raise e
|
|
62
|
+
logging.error(f"LLM error: {e}")
|
|
63
|
+
logging.info(f"Retrying... {tries} retries left")
|
|
64
|
+
continue
|
|
44
65
|
try:
|
|
45
66
|
response.gen_duration = (datetime.now() - start).total_seconds()
|
|
46
67
|
if not env().config.SAVE_MEMORY:
|
|
@@ -48,15 +69,35 @@ def llm(prompt: TPrompt, **kwargs) -> str | LLMResponse:
|
|
|
48
69
|
except AttributeError:
|
|
49
70
|
...
|
|
50
71
|
[h(response) for h in env().llm_after_handlers]
|
|
72
|
+
if tries > 0:
|
|
73
|
+
retry_params = dict(**kwargs)
|
|
74
|
+
retry_params["retries"] = tries - 1
|
|
75
|
+
setattr(
|
|
76
|
+
response,
|
|
77
|
+
"_retry_callback",
|
|
78
|
+
lambda: llm(prompt, **retry_params)
|
|
79
|
+
)
|
|
80
|
+
if parse_json:
|
|
81
|
+
parsing_params = parse_json if isinstance(parse_json, dict) else {}
|
|
82
|
+
return response.parse_json(**parsing_params)
|
|
51
83
|
return response
|
|
52
84
|
|
|
53
85
|
|
|
54
|
-
async def allm(
|
|
86
|
+
async def allm(
|
|
87
|
+
prompt: TPrompt,
|
|
88
|
+
retries: int = 0,
|
|
89
|
+
parse_json: bool | dict = False,
|
|
90
|
+
**kwargs
|
|
91
|
+
) -> str | LLMResponse | DictFromLLMResponse:
|
|
55
92
|
"""
|
|
56
93
|
Request Large Language Model asynchronously
|
|
57
94
|
|
|
58
95
|
Args:
|
|
59
96
|
prompt (str | Msg | dict | list[str | Msg | dict]): Text to send to LLM
|
|
97
|
+
retries (int): Number of retries in case of error
|
|
98
|
+
parse_json (bool|dict):
|
|
99
|
+
If True, parses response as JSON,
|
|
100
|
+
alternatively non-empty dict can be used as parse_json arguments
|
|
60
101
|
**kwargs (dict): Parameters supported by the LLM API
|
|
61
102
|
|
|
62
103
|
See parameters supported by the OpenAI:
|
|
@@ -87,7 +128,18 @@ async def allm(prompt: TPrompt, **kwargs) -> str | LLMResponse:
|
|
|
87
128
|
"""
|
|
88
129
|
[h(prompt, **kwargs) for h in env().llm_before_handlers]
|
|
89
130
|
start = datetime.now()
|
|
90
|
-
|
|
131
|
+
tries = retries + 1
|
|
132
|
+
while tries > 0:
|
|
133
|
+
try:
|
|
134
|
+
tries -= 1
|
|
135
|
+
response = await env().llm_async_function(prompt, **kwargs)
|
|
136
|
+
break
|
|
137
|
+
except Exception as e:
|
|
138
|
+
if tries == 0:
|
|
139
|
+
raise e
|
|
140
|
+
logging.error(f"LLM error: {e}")
|
|
141
|
+
logging.info(f"Retrying... {tries} retries left")
|
|
142
|
+
continue
|
|
91
143
|
try:
|
|
92
144
|
response.gen_duration = (datetime.now() - start).total_seconds()
|
|
93
145
|
if not env().config.SAVE_MEMORY:
|
|
@@ -95,6 +147,15 @@ async def allm(prompt: TPrompt, **kwargs) -> str | LLMResponse:
|
|
|
95
147
|
except AttributeError:
|
|
96
148
|
...
|
|
97
149
|
[h(response) for h in env().llm_after_handlers]
|
|
150
|
+
if parse_json:
|
|
151
|
+
try:
|
|
152
|
+
parsing_params = parse_json if isinstance(parse_json, dict) else {}
|
|
153
|
+
return response.parse_json(**parsing_params)
|
|
154
|
+
except Exception as e:
|
|
155
|
+
if tries > 0:
|
|
156
|
+
logging.error(f"LLM error: {e}")
|
|
157
|
+
logging.info(f"Retrying... {tries} retries left")
|
|
158
|
+
return await allm(prompt, retries=tries - 1, parse_json=parse_json, **kwargs)
|
|
98
159
|
return response
|
|
99
160
|
|
|
100
161
|
|
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
import os
|
|
2
|
+
from dataclasses import dataclass, asdict
|
|
2
3
|
from datetime import datetime
|
|
3
4
|
import aiohttp
|
|
4
5
|
from .._env import env
|
|
5
6
|
|
|
6
7
|
|
|
8
|
+
@dataclass
|
|
9
|
+
class TTSArgs:
|
|
10
|
+
text: str
|
|
11
|
+
out_file: str = None
|
|
12
|
+
voice: str = "D38z5RcWu1voky8WS1ja"
|
|
13
|
+
stability: float = 0.29
|
|
14
|
+
similarity_boost: float = 0.5
|
|
15
|
+
style: float = 0.0
|
|
16
|
+
chunk_size: int = 1024
|
|
17
|
+
speed: float = 1.0
|
|
18
|
+
use_speaker_boost: bool = False
|
|
19
|
+
previous_text: str = None
|
|
20
|
+
next_text: str = None
|
|
21
|
+
|
|
22
|
+
def to_dict(self) -> dict:
|
|
23
|
+
return asdict(self)
|
|
24
|
+
|
|
25
|
+
|
|
7
26
|
async def text_to_speech(
|
|
8
27
|
text: str,
|
|
9
28
|
out_file: str = None,
|
|
@@ -12,6 +31,10 @@ async def text_to_speech(
|
|
|
12
31
|
similarity_boost=0.5,
|
|
13
32
|
style=0.0,
|
|
14
33
|
chunk_size=1024,
|
|
34
|
+
speed=1.0,
|
|
35
|
+
use_speaker_boost: bool = False,
|
|
36
|
+
previous_text: str = None,
|
|
37
|
+
next_text: str = None,
|
|
15
38
|
) -> str:
|
|
16
39
|
url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice}"
|
|
17
40
|
if not out_file:
|
|
@@ -25,8 +48,15 @@ async def text_to_speech(
|
|
|
25
48
|
"stability": stability,
|
|
26
49
|
"similarity_boost": similarity_boost,
|
|
27
50
|
"style": style,
|
|
51
|
+
"speed": speed,
|
|
28
52
|
},
|
|
29
53
|
}
|
|
54
|
+
if use_speaker_boost:
|
|
55
|
+
data["voice_settings"]["use_speaker_boost"] = use_speaker_boost
|
|
56
|
+
if previous_text:
|
|
57
|
+
data["previous_text"] = previous_text
|
|
58
|
+
if next_text:
|
|
59
|
+
data["next_text"] = next_text
|
|
30
60
|
headers = {
|
|
31
61
|
"Accept": "audio/mpeg",
|
|
32
62
|
"Content-Type": "application/json",
|
|
@@ -5,6 +5,7 @@ from .message_types import Msg
|
|
|
5
5
|
|
|
6
6
|
if TYPE_CHECKING:
|
|
7
7
|
from .wrappers.prompt_wrapper import PromptWrapper # noqa: F401
|
|
8
|
+
from .wrappers.llm_response_wrapper import LLMResponse # noqa: F401
|
|
8
9
|
|
|
9
10
|
TPrompt = Union[
|
|
10
11
|
dict, Msg, str, "PromptWrapper", List[Union[dict, Msg, str, "PromptWrapper"]]
|
|
@@ -12,9 +13,9 @@ TPrompt = Union[
|
|
|
12
13
|
"""Type for prompt argument in LLM requests"""
|
|
13
14
|
TplFunctionType = Callable[[Union[PathLike[str], str], Any], str]
|
|
14
15
|
"""Function type for rendering prompt templates"""
|
|
15
|
-
LLMFunctionType = Callable[[TPrompt, Any],
|
|
16
|
+
LLMFunctionType = Callable[[TPrompt, Any], "LLMResponse"]
|
|
16
17
|
"""Function type for requesting LLM synchronously"""
|
|
17
|
-
LLMAsyncFunctionType = Callable[[TPrompt, Any], Awaitable[
|
|
18
|
+
LLMAsyncFunctionType = Callable[[TPrompt, Any], Awaitable["LLMResponse"]]
|
|
18
19
|
"""Function type for requesting LLM asynchronously"""
|
|
19
20
|
|
|
20
21
|
|
{ai_microcore-4.0.0.dev4 → ai_microcore-4.0.0.dev5}/microcore/wrappers/llm_response_wrapper.py
RENAMED
|
@@ -46,9 +46,27 @@ class LLMResponse(ExtendedString, ConvertableToMessage):
|
|
|
46
46
|
return obj
|
|
47
47
|
|
|
48
48
|
def parse_json(
|
|
49
|
-
self,
|
|
49
|
+
self,
|
|
50
|
+
raise_errors: bool = True,
|
|
51
|
+
required_fields: list[str] = None,
|
|
52
|
+
validator: callable = None,
|
|
50
53
|
) -> list | dict | float | int | str | DictFromLLMResponse:
|
|
51
|
-
|
|
54
|
+
try:
|
|
55
|
+
res = parse_json(self.content, True, required_fields)
|
|
56
|
+
if validator:
|
|
57
|
+
try:
|
|
58
|
+
validator(res)
|
|
59
|
+
except Exception as e:
|
|
60
|
+
raise BadAIAnswer(f"Language model response validation failed: {e}") from None
|
|
61
|
+
except Exception as e:
|
|
62
|
+
if hasattr(self, "_retry_callback"):
|
|
63
|
+
res = self._retry_callback()
|
|
64
|
+
if isinstance(res, DictFromLLMResponse):
|
|
65
|
+
return res
|
|
66
|
+
return res.parse_json(raise_errors, required_fields, validator)
|
|
67
|
+
if raise_errors:
|
|
68
|
+
raise e
|
|
69
|
+
res = False
|
|
52
70
|
if isinstance(res, dict):
|
|
53
71
|
res = DictFromLLMResponse(res)
|
|
54
72
|
res.llm_response = self
|
|
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
|