ai-microcore 4.0.0.dev18__tar.gz → 4.0.0.dev20__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.dev18 → ai_microcore-4.0.0.dev20}/PKG-INFO +4 -3
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/README.md +3 -2
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/__init__.py +1 -1
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/mcp.py +38 -98
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/tokenizing.py +2 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/LICENSE +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/_env.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/_llm_functions.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/_prepare_llm_args.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/ai_func/__init__.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/ai_func/ai-func.json.j2 +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/ai_func/ai-func.pythonic.j2 +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/ai_modules.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/configuration.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/embedding_db/__init__.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/embedding_db/chromadb.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/file_storage.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/interactive_setup.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/json_parsing.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/llm/__init__.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/llm/_openai_llm_v0.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/llm/_openai_llm_v1.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/llm/anthropic.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/llm/google_genai.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/llm/google_vertex_ai.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/llm/local_llm.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/llm/local_transformers.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/llm/openai_llm.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/llm/shared.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/logging.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/message_types.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/metrics.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/python.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/templating/__init__.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/templating/jinja2.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/text2speech/elevenlabs.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/types.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/ui.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/utils.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/wrappers/__init__.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/wrappers/llm_response_wrapper.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/wrappers/prompt_wrapper.py +0 -0
- {ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/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.dev20
|
|
4
4
|
Summary: # Minimalistic Foundation for AI Applications
|
|
5
5
|
Keywords: llm,large language models,ai,similarity search,ai search,gpt,openai,framework,adapter
|
|
6
6
|
Author-email: Vitalii Stepanenko <mail@vitalii.in>
|
|
@@ -27,10 +27,11 @@ Requires-Dist: mcp~=1.9.1
|
|
|
27
27
|
Requires-Dist: docstring_parser~=0.16.0
|
|
28
28
|
Project-URL: Source Code, https://github.com/Nayjest/ai-microcore
|
|
29
29
|
|
|
30
|
-
<p align="right">
|
|
31
|
-
<a href="https://github.com/Nayjest/ai-microcore/releases" target="_blank"><img src="https://img.shields.io/github/release/ai-microcore
|
|
30
|
+
<p align="right">
|
|
31
|
+
<a href="https://github.com/Nayjest/ai-microcore/releases" target="_blank"><img src="https://img.shields.io/github/v/release/Nayjest/ai-microcore.svg" alt="Release Notes"></a>
|
|
32
32
|
<a href="https://app.codacy.com/gh/Nayjest/ai-microcore/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade" target="_blank"><img src="https://app.codacy.com/project/badge/Grade/441d03416bc048828c649129530dcbc3" alt="Code Quality"></a>
|
|
33
33
|
<a href="https://github.com/Nayjest/ai-microcore/actions/workflows/pylint.yml" target="_blank"><img src="https://github.com/Nayjest/ai-microcore/actions/workflows/pylint.yml/badge.svg" alt="Pylint"></a>
|
|
34
|
+
<img src="coverage.svg" alt="Code Coverage">
|
|
34
35
|
<a href="https://github.com/Nayjest/ai-microcore/actions/workflows/tests.yml" target="_blank"><img src="https://github.com/Nayjest/ai-microcore/actions/workflows/tests.yml/badge.svg" alt="Tests"></a>
|
|
35
36
|
<a href="https://github.com/Nayjest/ai-microcore/blob/main/LICENSE" target="_blank"><img src="https://img.shields.io/static/v1?label=license&message=MIT&color=d08aff" alt="License"></a>
|
|
36
37
|
</p>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
<p align="right">
|
|
2
|
-
<a href="https://github.com/Nayjest/ai-microcore/releases" target="_blank"><img src="https://img.shields.io/github/release/ai-microcore
|
|
1
|
+
<p align="right">
|
|
2
|
+
<a href="https://github.com/Nayjest/ai-microcore/releases" target="_blank"><img src="https://img.shields.io/github/v/release/Nayjest/ai-microcore.svg" alt="Release Notes"></a>
|
|
3
3
|
<a href="https://app.codacy.com/gh/Nayjest/ai-microcore/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade" target="_blank"><img src="https://app.codacy.com/project/badge/Grade/441d03416bc048828c649129530dcbc3" alt="Code Quality"></a>
|
|
4
4
|
<a href="https://github.com/Nayjest/ai-microcore/actions/workflows/pylint.yml" target="_blank"><img src="https://github.com/Nayjest/ai-microcore/actions/workflows/pylint.yml/badge.svg" alt="Pylint"></a>
|
|
5
|
+
<img src="coverage.svg" alt="Code Coverage">
|
|
5
6
|
<a href="https://github.com/Nayjest/ai-microcore/actions/workflows/tests.yml" target="_blank"><img src="https://github.com/Nayjest/ai-microcore/actions/workflows/tests.yml/badge.svg" alt="Tests"></a>
|
|
6
7
|
<a href="https://github.com/Nayjest/ai-microcore/blob/main/LICENSE" target="_blank"><img src="https://img.shields.io/static/v1?label=license&message=MIT&color=d08aff" alt="License"></a>
|
|
7
8
|
</p>
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import logging
|
|
3
|
+
import datetime
|
|
3
4
|
from typing import Optional
|
|
4
5
|
from dataclasses import dataclass, field
|
|
5
6
|
from enum import Enum
|
|
6
7
|
|
|
7
8
|
import requests
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
|
|
9
|
+
from fastmcp import Client
|
|
10
|
+
from fastmcp.client.progress import ProgressHandler
|
|
11
|
+
import mcp.types
|
|
11
12
|
|
|
12
13
|
from .utils import ExtendedString, ConvertableToMessage
|
|
13
14
|
from .ai_func import AiFuncSyntax
|
|
@@ -64,13 +65,8 @@ class McpTransport(str, Enum):
|
|
|
64
65
|
class MCPConnection:
|
|
65
66
|
url: str = None
|
|
66
67
|
transport: McpTransport = field(default=McpTransport.STREAMABLE_HTTP)
|
|
67
|
-
read_stream: any = None
|
|
68
|
-
write_stream: any = None
|
|
69
|
-
context_manager: any = None
|
|
70
|
-
session: ClientSession = field(default=None, init=False)
|
|
71
68
|
tools: Optional["Tools"] = field(default=None, init=False)
|
|
72
|
-
|
|
73
|
-
_del_event: asyncio.Event = field(default=None, init=False)
|
|
69
|
+
_client: Client | None = field(default=None, init=False)
|
|
74
70
|
|
|
75
71
|
@staticmethod
|
|
76
72
|
async def init(
|
|
@@ -80,88 +76,21 @@ class MCPConnection:
|
|
|
80
76
|
use_cache: bool = True,
|
|
81
77
|
connect_timeout: float = 10,
|
|
82
78
|
) -> "MCPConnection":
|
|
83
|
-
|
|
84
|
-
del_event = asyncio.Event()
|
|
85
|
-
opened_event = asyncio.Event()
|
|
86
79
|
con: MCPConnection = MCPConnection()
|
|
87
|
-
con.
|
|
88
|
-
|
|
89
|
-
#
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
logging.info(f"Connecting to {transport} MCP {url}...")
|
|
93
|
-
if transport == McpTransport.STREAMABLE_HTTP:
|
|
94
|
-
context_manager = streamablehttp_client(url)
|
|
95
|
-
(
|
|
96
|
-
read_stream,
|
|
97
|
-
write_stream,
|
|
98
|
-
_
|
|
99
|
-
) = await context_manager.__aenter__() # pylint: disable=E1101
|
|
100
|
-
elif transport == McpTransport.SSE:
|
|
101
|
-
context_manager = sse_client(url)
|
|
102
|
-
(
|
|
103
|
-
read_stream,
|
|
104
|
-
write_stream
|
|
105
|
-
) = await context_manager.__aenter__() # pylint: disable=E1101
|
|
106
|
-
else:
|
|
107
|
-
raise ValueError(f"Unsupported transport type: {transport}")
|
|
108
|
-
con.url = url
|
|
109
|
-
con.transport = transport
|
|
110
|
-
con.read_stream = read_stream
|
|
111
|
-
con.write_stream = write_stream
|
|
112
|
-
con.context_manager = context_manager
|
|
113
|
-
await con.init_session()
|
|
114
|
-
if fetch_tools:
|
|
115
|
-
await con.fetch_tools(use_cache=use_cache)
|
|
116
|
-
opened_event.set()
|
|
117
|
-
|
|
118
|
-
finally:
|
|
119
|
-
await del_event.wait()
|
|
120
|
-
await con._close() # pylint: disable=W0212
|
|
121
|
-
|
|
122
|
-
con._lifecycle_task = asyncio.create_task(lifecycle()) # pylint: disable=W0212
|
|
123
|
-
try:
|
|
124
|
-
await asyncio.wait_for(opened_event.wait(), timeout=connect_timeout)
|
|
125
|
-
except Exception as e:
|
|
126
|
-
logging.warning(f"Failed to connect to MCP {url}: {e}")
|
|
127
|
-
try:
|
|
128
|
-
await con._close() # pylint: disable=W0212
|
|
129
|
-
except: # noqa: E722 # pylint: disable=W0702
|
|
130
|
-
pass
|
|
131
|
-
raise
|
|
80
|
+
con.transport = transport
|
|
81
|
+
con._client = Client(url, timeout=connect_timeout) # pylint: disable=W0212
|
|
82
|
+
await con._client.__aenter__() # pylint: disable=E1101,W0212,C2801
|
|
83
|
+
if fetch_tools:
|
|
84
|
+
await con.fetch_tools(use_cache=use_cache)
|
|
132
85
|
return con
|
|
133
86
|
|
|
134
87
|
async def close(self):
|
|
135
|
-
self.
|
|
136
|
-
|
|
137
|
-
|
|
88
|
+
if self._client:
|
|
89
|
+
await self._client.__aexit__(None, None, None)
|
|
90
|
+
self._client = None
|
|
138
91
|
else:
|
|
139
92
|
logging.error(f"Trying to close MCP connection that is not opened ({self.url})")
|
|
140
93
|
|
|
141
|
-
async def _close(self):
|
|
142
|
-
logging.info(f"Closing MCP session ({self.url})...")
|
|
143
|
-
try:
|
|
144
|
-
if self.session:
|
|
145
|
-
await self.session.__aexit__(None, None, None)
|
|
146
|
-
del self.session
|
|
147
|
-
self.session = None
|
|
148
|
-
finally:
|
|
149
|
-
logging.info(f"Closing MCP connection ({self.url})...")
|
|
150
|
-
try:
|
|
151
|
-
if self.context_manager:
|
|
152
|
-
await self.context_manager.__aexit__(None, None, None)
|
|
153
|
-
del self.context_manager
|
|
154
|
-
self.context_manager = None
|
|
155
|
-
finally:
|
|
156
|
-
logging.info(f"Closed CTX ({self.url})")
|
|
157
|
-
|
|
158
|
-
async def init_session(self):
|
|
159
|
-
logging.info(f"Initializing MCP session ({self.url})")
|
|
160
|
-
self.session = ClientSession(self.read_stream, self.write_stream)
|
|
161
|
-
await self.session.__aenter__() # pylint: disable=unnecessary-dunder-call
|
|
162
|
-
await self.session.initialize()
|
|
163
|
-
return self.session
|
|
164
|
-
|
|
165
94
|
async def fetch_tools(self, use_cache: bool = True) -> "Tools":
|
|
166
95
|
if self.tools is not None:
|
|
167
96
|
return self.tools
|
|
@@ -172,8 +101,8 @@ class MCPConnection:
|
|
|
172
101
|
return self.tools
|
|
173
102
|
|
|
174
103
|
logging.info("Fetching tools from MCP %s", ui.green(self.url))
|
|
175
|
-
mcp_tools = await self.
|
|
176
|
-
self.tools = Tools.from_list([Tool.from_mcp(tool) for tool in mcp_tools
|
|
104
|
+
mcp_tools = await self._client.list_tools()
|
|
105
|
+
self.tools = Tools.from_list([Tool.from_mcp(tool) for tool in mcp_tools])
|
|
177
106
|
if use_cache:
|
|
178
107
|
self.update_tools_cache()
|
|
179
108
|
return self.tools
|
|
@@ -183,17 +112,24 @@ class MCPConnection:
|
|
|
183
112
|
raise RuntimeError("Tools are not fetched yet. Call fetch_tools() first.")
|
|
184
113
|
ToolsCache.write(self.url, self.tools)
|
|
185
114
|
|
|
186
|
-
def
|
|
187
|
-
self
|
|
188
|
-
|
|
189
|
-
|
|
115
|
+
async def call(
|
|
116
|
+
self,
|
|
117
|
+
name: str,
|
|
118
|
+
timeout: datetime.timedelta | float | int | None = None,
|
|
119
|
+
progress_handler: ProgressHandler | None = None,
|
|
120
|
+
**kwargs
|
|
121
|
+
):
|
|
190
122
|
assert env().config.AI_SYNTAX_FUNCTION_NAME_FIELD not in kwargs
|
|
191
123
|
params = dict(kwargs)
|
|
192
124
|
params[env().config.AI_SYNTAX_FUNCTION_NAME_FIELD] = name
|
|
193
|
-
return await self.exec(params)
|
|
194
|
-
|
|
125
|
+
return await self.exec(params, timeout=timeout, progress_handler=progress_handler)
|
|
195
126
|
|
|
196
|
-
async def exec(
|
|
127
|
+
async def exec(
|
|
128
|
+
self,
|
|
129
|
+
params: dict | LLMResponse,
|
|
130
|
+
timeout: datetime.timedelta | float | int | None = None,
|
|
131
|
+
progress_handler: ProgressHandler | None = None,
|
|
132
|
+
):
|
|
197
133
|
if isinstance(params, LLMResponse):
|
|
198
134
|
try:
|
|
199
135
|
params = params.parse_json(
|
|
@@ -209,11 +145,15 @@ class MCPConnection:
|
|
|
209
145
|
f"Tool name should be passed in {env().config.AI_SYNTAX_FUNCTION_NAME_FIELD} field"
|
|
210
146
|
)
|
|
211
147
|
logging.info(f"Calling MCP tool {ui.green(name)} with {params}...")
|
|
212
|
-
|
|
213
|
-
|
|
148
|
+
content = await self._client.call_tool(
|
|
149
|
+
name=name,
|
|
150
|
+
arguments=params,
|
|
151
|
+
timeout=timeout,
|
|
152
|
+
progress_handler=progress_handler
|
|
153
|
+
)
|
|
214
154
|
if content and len(content) == 1 and content[0].type == "text":
|
|
215
|
-
return MCPAnswer(content[0].text,
|
|
216
|
-
return
|
|
155
|
+
return MCPAnswer(content[0].text, dict(response=content))
|
|
156
|
+
return content
|
|
217
157
|
|
|
218
158
|
|
|
219
159
|
@dataclass
|
|
@@ -242,7 +182,7 @@ class Tool:
|
|
|
242
182
|
self.args[key] = Tool.Arg(**self.args[key])
|
|
243
183
|
|
|
244
184
|
@staticmethod
|
|
245
|
-
def from_mcp(tool: types.Tool) -> "Tool":
|
|
185
|
+
def from_mcp(tool: mcp.types.Tool) -> "Tool":
|
|
246
186
|
t = Tool(
|
|
247
187
|
name=tool.name,
|
|
248
188
|
description=tool.description,
|
|
@@ -25,6 +25,8 @@ def _resolve_tiktoken_encoding(
|
|
|
25
25
|
)
|
|
26
26
|
if for_model:
|
|
27
27
|
try:
|
|
28
|
+
if for_model.startswith("gpt-4.1") or for_model.startswith("gpt-4.5"):
|
|
29
|
+
return tiktoken.get_encoding("o200k_base")
|
|
28
30
|
return tiktoken.encoding_for_model(for_model)
|
|
29
31
|
except (KeyError, requests.exceptions.ConnectionError):
|
|
30
32
|
logging.warning(
|
|
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
|
{ai_microcore-4.0.0.dev18 → ai_microcore-4.0.0.dev20}/microcore/wrappers/llm_response_wrapper.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|