beamlit 0.0.28rc25__py3-none-any.whl → 0.0.29rc26__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- beamlit/agents/chain.py +93 -0
- beamlit/agents/decorator.py +6 -2
- beamlit/authentication/authentication.py +2 -2
- beamlit/authentication/clientcredentials.py +1 -1
- beamlit/common/settings.py +3 -5
- beamlit/functions/remote/remote.py +37 -20
- {beamlit-0.0.28rc25.dist-info → beamlit-0.0.29rc26.dist-info}/METADATA +1 -1
- {beamlit-0.0.28rc25.dist-info → beamlit-0.0.29rc26.dist-info}/RECORD +9 -8
- {beamlit-0.0.28rc25.dist-info → beamlit-0.0.29rc26.dist-info}/WHEEL +0 -0
beamlit/agents/chain.py
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
import asyncio
|
2
|
+
from dataclasses import dataclass
|
3
|
+
import warnings
|
4
|
+
from typing import Any, Callable
|
5
|
+
|
6
|
+
import pydantic
|
7
|
+
import typing_extensions as t
|
8
|
+
from beamlit.api.agents import list_agents
|
9
|
+
from beamlit.authentication.authentication import AuthenticatedClient
|
10
|
+
from beamlit.models import Agent, AgentChain
|
11
|
+
from beamlit.run import RunClient
|
12
|
+
from beamlit.common.settings import get_settings
|
13
|
+
from langchain_core.tools.base import BaseTool, ToolException
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
class ChainTool(BaseTool):
|
18
|
+
"""
|
19
|
+
Chain tool
|
20
|
+
"""
|
21
|
+
|
22
|
+
client: RunClient
|
23
|
+
handle_tool_error: bool | str | Callable[[ToolException], str] | None = True
|
24
|
+
|
25
|
+
@t.override
|
26
|
+
def _run(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
|
27
|
+
warnings.warn(
|
28
|
+
"Invoke this tool asynchronousely using `ainvoke`. This method exists only to satisfy standard tests.",
|
29
|
+
stacklevel=1,
|
30
|
+
)
|
31
|
+
return asyncio.run(self._arun(*args, **kwargs))
|
32
|
+
|
33
|
+
@t.override
|
34
|
+
async def _arun(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
|
35
|
+
settings = get_settings()
|
36
|
+
result = self.client.run(
|
37
|
+
"agent",
|
38
|
+
self.name,
|
39
|
+
settings.environment,
|
40
|
+
"POST",
|
41
|
+
json=kwargs,
|
42
|
+
)
|
43
|
+
return result.text
|
44
|
+
|
45
|
+
@t.override
|
46
|
+
@property
|
47
|
+
def tool_call_schema(self) -> type[pydantic.BaseModel]:
|
48
|
+
assert self.args_schema is not None # noqa: S101
|
49
|
+
return self.args_schema
|
50
|
+
|
51
|
+
class ChainInput(pydantic.BaseModel):
|
52
|
+
inputs: str
|
53
|
+
|
54
|
+
@dataclass
|
55
|
+
class ChainToolkit:
|
56
|
+
"""
|
57
|
+
Remote toolkit
|
58
|
+
"""
|
59
|
+
client: AuthenticatedClient
|
60
|
+
chain: list[AgentChain]
|
61
|
+
_chain: list[Agent] | None = None
|
62
|
+
|
63
|
+
model_config = pydantic.ConfigDict(arbitrary_types_allowed=True)
|
64
|
+
|
65
|
+
def initialize(self) -> None:
|
66
|
+
"""Initialize the session and retrieve tools list"""
|
67
|
+
if self._chain is None:
|
68
|
+
agents = list_agents.sync_detailed(
|
69
|
+
client=self.client,
|
70
|
+
).parsed
|
71
|
+
chain_enabled = [chain for chain in self.chain if chain.enabled]
|
72
|
+
agents_chain = []
|
73
|
+
for chain in chain_enabled:
|
74
|
+
agent = [agent for agent in agents if agent.metadata.name == chain.name]
|
75
|
+
if agent:
|
76
|
+
agent[0].spec.description = chain.description or agent[0].spec.description
|
77
|
+
agents_chain.append(agent[0])
|
78
|
+
self._chain = agents_chain
|
79
|
+
|
80
|
+
@t.override
|
81
|
+
def get_tools(self) -> list[BaseTool]:
|
82
|
+
if self._chain is None:
|
83
|
+
raise RuntimeError("Must initialize the toolkit first")
|
84
|
+
|
85
|
+
return [
|
86
|
+
ChainTool(
|
87
|
+
client=RunClient(self.client),
|
88
|
+
name=agent.metadata.name,
|
89
|
+
description=agent.spec.description or "",
|
90
|
+
args_schema=ChainInput,
|
91
|
+
)
|
92
|
+
for agent in self._chain
|
93
|
+
]
|
beamlit/agents/decorator.py
CHANGED
@@ -18,7 +18,7 @@ from langgraph.checkpoint.memory import MemorySaver
|
|
18
18
|
from langgraph.prebuilt import create_react_agent
|
19
19
|
|
20
20
|
from .chat import get_chat_model
|
21
|
-
|
21
|
+
from .chain import ChainToolkit
|
22
22
|
|
23
23
|
def get_functions(dir="src/functions", from_decorator="function"):
|
24
24
|
functions = []
|
@@ -178,7 +178,6 @@ def agent(
|
|
178
178
|
logger.warn(f"Failed to initialize MCP server {server}: {e!s}")
|
179
179
|
|
180
180
|
if remote_functions:
|
181
|
-
|
182
181
|
for function in remote_functions:
|
183
182
|
try:
|
184
183
|
toolkit = RemoteToolkit(client, function)
|
@@ -187,6 +186,11 @@ def agent(
|
|
187
186
|
except Exception as e:
|
188
187
|
logger.warn(f"Failed to initialize remote function {function}: {e!s}")
|
189
188
|
|
189
|
+
if agent.spec.agent_chain:
|
190
|
+
toolkit = ChainToolkit(client, agent.spec.agent_chain)
|
191
|
+
toolkit.initialize()
|
192
|
+
functions.extend(toolkit.get_tools())
|
193
|
+
|
190
194
|
if override_agent is None and len(functions) == 0:
|
191
195
|
raise ValueError(
|
192
196
|
"You must define at least one function, you can define this function in directory "
|
@@ -47,15 +47,15 @@ def new_client_from_settings(settings: Settings):
|
|
47
47
|
|
48
48
|
|
49
49
|
def new_client():
|
50
|
+
settings = get_settings()
|
50
51
|
context = current_context()
|
51
|
-
if context.workspace:
|
52
|
+
if context.workspace and not settings.authentication.client.credentials:
|
52
53
|
credentials = load_credentials(context.workspace)
|
53
54
|
client_config = RunClientWithCredentials(
|
54
55
|
credentials=credentials,
|
55
56
|
workspace=context.workspace,
|
56
57
|
)
|
57
58
|
else:
|
58
|
-
settings = get_settings()
|
59
59
|
credentials = load_credentials_from_settings(settings)
|
60
60
|
client_config = RunClientWithCredentials(
|
61
61
|
credentials=credentials,
|
@@ -37,7 +37,7 @@ class ClientCredentials(Auth):
|
|
37
37
|
def refresh_if_needed(self) -> Optional[Exception]:
|
38
38
|
settings = get_settings()
|
39
39
|
if self.credentials.client_credentials and not self.credentials.refresh_token:
|
40
|
-
headers = {"Authorization": f"Basic {self.credentials.client_credentials}"}
|
40
|
+
headers = {"Authorization": f"Basic {self.credentials.client_credentials}", "Content-Type": "application/json"}
|
41
41
|
body = {"grant_type": "client_credentials"}
|
42
42
|
response = requests.post(f"{settings.base_url}/oauth/token", headers=headers, json=body)
|
43
43
|
response.raise_for_status()
|
beamlit/common/settings.py
CHANGED
@@ -18,11 +18,6 @@ from pydantic_settings import (BaseSettings, PydanticBaseSettingsSource,
|
|
18
18
|
global SETTINGS
|
19
19
|
SETTINGS = None
|
20
20
|
|
21
|
-
|
22
|
-
def get_settings():
|
23
|
-
return SETTINGS
|
24
|
-
|
25
|
-
|
26
21
|
class SettingsAgent(BaseSettings):
|
27
22
|
agent: Union[None, CompiledGraph, BaseChatModel] = None
|
28
23
|
chain: Union[Unset, list[Agent]] = UNSET
|
@@ -96,6 +91,9 @@ class Settings(BaseSettings):
|
|
96
91
|
init_settings,
|
97
92
|
)
|
98
93
|
|
94
|
+
def get_settings() -> Settings:
|
95
|
+
return SETTINGS
|
96
|
+
|
99
97
|
|
100
98
|
def init_agent(
|
101
99
|
client: AuthenticatedClient,
|
@@ -1,20 +1,21 @@
|
|
1
1
|
import asyncio
|
2
|
-
import urllib.parse
|
3
2
|
import warnings
|
4
3
|
from typing import Any, Callable
|
5
4
|
|
6
5
|
import pydantic
|
7
|
-
import pydantic_core
|
8
6
|
import typing_extensions as t
|
7
|
+
from dataclasses import dataclass
|
9
8
|
from beamlit.api.functions import get_function
|
10
9
|
from beamlit.authentication.authentication import AuthenticatedClient
|
11
|
-
from beamlit.
|
12
|
-
from
|
10
|
+
from beamlit.run import RunClient
|
11
|
+
from beamlit.common.settings import get_settings
|
12
|
+
from beamlit.models import Function, StoreFunctionParameter
|
13
|
+
from langchain_core.tools.base import BaseTool, ToolException
|
13
14
|
from pydantic.json_schema import JsonSchemaValue
|
14
15
|
from pydantic_core import core_schema as cs
|
15
16
|
|
16
17
|
|
17
|
-
def create_schema_model(
|
18
|
+
def create_schema_model(parameters: list[StoreFunctionParameter]) -> type[pydantic.BaseModel]:
|
18
19
|
# Create a new model class that returns our JSON schema.
|
19
20
|
# LangChain requires a BaseModel class.
|
20
21
|
class Schema(pydantic.BaseModel):
|
@@ -25,6 +26,18 @@ def create_schema_model(schema: dict[str, t.Any]) -> type[pydantic.BaseModel]:
|
|
25
26
|
def __get_pydantic_json_schema__(
|
26
27
|
cls, core_schema: cs.CoreSchema, handler: pydantic.GetJsonSchemaHandler
|
27
28
|
) -> JsonSchemaValue:
|
29
|
+
schema = {
|
30
|
+
"type": "object",
|
31
|
+
"properties": {},
|
32
|
+
"required": [],
|
33
|
+
}
|
34
|
+
for parameter in parameters:
|
35
|
+
schema["properties"][parameter.name] = {
|
36
|
+
"type": parameter.type_,
|
37
|
+
"description": parameter.description,
|
38
|
+
}
|
39
|
+
if parameter.required:
|
40
|
+
schema["required"].append(parameter.name)
|
28
41
|
return schema
|
29
42
|
|
30
43
|
return Schema
|
@@ -35,7 +48,7 @@ class RemoteTool(BaseTool):
|
|
35
48
|
Remote tool
|
36
49
|
"""
|
37
50
|
|
38
|
-
client:
|
51
|
+
client: RunClient
|
39
52
|
handle_tool_error: bool | str | Callable[[ToolException], str] | None = True
|
40
53
|
|
41
54
|
@t.override
|
@@ -48,12 +61,15 @@ class RemoteTool(BaseTool):
|
|
48
61
|
|
49
62
|
@t.override
|
50
63
|
async def _arun(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
64
|
+
settings = get_settings()
|
65
|
+
result = self.client.run(
|
66
|
+
"function",
|
67
|
+
self.name,
|
68
|
+
settings.environment,
|
69
|
+
"POST",
|
70
|
+
kwargs,
|
71
|
+
)
|
72
|
+
return result.text
|
57
73
|
|
58
74
|
@t.override
|
59
75
|
@property
|
@@ -61,7 +77,8 @@ class RemoteTool(BaseTool):
|
|
61
77
|
assert self.args_schema is not None # noqa: S101
|
62
78
|
return self.args_schema
|
63
79
|
|
64
|
-
|
80
|
+
@dataclass
|
81
|
+
class RemoteToolkit:
|
65
82
|
"""
|
66
83
|
Remote toolkit
|
67
84
|
"""
|
@@ -75,27 +92,27 @@ class RemoteToolkit(BaseToolkit):
|
|
75
92
|
def initialize(self) -> None:
|
76
93
|
"""Initialize the session and retrieve tools list"""
|
77
94
|
if self._function is None:
|
78
|
-
self._function = get_function(self.function, client=self.client)
|
95
|
+
self._function = get_function.sync_detailed(self.function, client=self.client).parsed
|
79
96
|
|
80
97
|
@t.override
|
81
98
|
def get_tools(self) -> list[BaseTool]:
|
82
|
-
if self.
|
99
|
+
if self._function is None:
|
83
100
|
raise RuntimeError("Must initialize the toolkit first")
|
84
101
|
|
85
102
|
if self._function.spec.kit:
|
86
103
|
return [
|
87
104
|
RemoteTool(
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
105
|
+
client=RunClient(self.client),
|
106
|
+
name=func.name,
|
107
|
+
description=func.description or "",
|
108
|
+
args_schema=create_schema_model(func.parameters),
|
92
109
|
)
|
93
110
|
for func in self._function.spec.kit
|
94
111
|
]
|
95
112
|
|
96
113
|
return [
|
97
114
|
RemoteTool(
|
98
|
-
client=self.client,
|
115
|
+
client=RunClient(self.client),
|
99
116
|
name=self._function.metadata.name,
|
100
117
|
description=self._function.spec.description or "",
|
101
118
|
args_schema=create_schema_model(self._function.spec.parameters),
|
@@ -5,8 +5,9 @@ beamlit/py.typed,sha256=8ZJUsxZiuOy1oJeVhsTWQhTG_6pTVHVXk5hJL79ebTk,25
|
|
5
5
|
beamlit/run.py,sha256=RLwMv5f_S8lw7Wq7O6DvEcOl0nGYh769qjGl_SmR9Z0,1338
|
6
6
|
beamlit/types.py,sha256=E1hhDh_zXfsSQ0NCt9-uw90_Mr5iIlsdfnfvxv5HarU,1005
|
7
7
|
beamlit/agents/__init__.py,sha256=nf1iwQwGtCG6nDqyVhxfWoqR6dv6X3bvSpCeqkTCFaM,101
|
8
|
+
beamlit/agents/chain.py,sha256=HzBs3nI4xaH86I_r-M-HGGp6roXsJxMx-qXl_GrJaY0,2831
|
8
9
|
beamlit/agents/chat.py,sha256=gVyv4FGBdQTDhdutX8l64OUNa6Fdqaw4eCfEDRH0IPQ,3558
|
9
|
-
beamlit/agents/decorator.py,sha256=
|
10
|
+
beamlit/agents/decorator.py,sha256=4JFITRjRLuNpaaSTFkj1ZL5B2PQRXY-a5VBoZ_2NSPw,9479
|
10
11
|
beamlit/api/__init__.py,sha256=zTSiG_ujSjAqWPyc435YXaX9XTlpMjiJWBbV-f-YtdA,45
|
11
12
|
beamlit/api/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
13
|
beamlit/api/agents/create_agent.py,sha256=t5Pr62My2EhQlcIY71MrI73-0_q5Djr3a_Ybt9MIiQQ,3587
|
@@ -123,8 +124,8 @@ beamlit/api/workspaces/update_workspace.py,sha256=qa5DV2UJSUYuB_ibALb4E9ghKpT1Ha
|
|
123
124
|
beamlit/api/workspaces/update_workspace_user_role.py,sha256=Yn9iuJ4tKtauzBiJyU4-wYUMS9g98X2Om8zs7UkzrY8,4917
|
124
125
|
beamlit/authentication/__init__.py,sha256=wiXqRbc7E-ulrH_ueA9duOGFvXeo7-RvhSD1XbFogMo,1020
|
125
126
|
beamlit/authentication/apikey.py,sha256=KNBTgdi0VBzBAAmSwU2X1QoB58vRbg8wkXb8-GTZCQo,657
|
126
|
-
beamlit/authentication/authentication.py,sha256=
|
127
|
-
beamlit/authentication/clientcredentials.py,sha256=
|
127
|
+
beamlit/authentication/authentication.py,sha256=ItVo1olbqHtHmIMz5ILT-T5m4j3AqN7XbQKeUE9-8o8,3358
|
128
|
+
beamlit/authentication/clientcredentials.py,sha256=cxZPPu--CgizwqX0pdfFQ91gJt1EFKwyy-aBB_dXX7I,3990
|
128
129
|
beamlit/authentication/credentials.py,sha256=p_1xenabCbQuRz7BiFk7oTK4uCxAt_zoyku5o-jcKGE,5343
|
129
130
|
beamlit/authentication/device_mode.py,sha256=tmr22gllKOZwBRub_QjF5pYa425x-nE8tQNpZ_EGR6g,3644
|
130
131
|
beamlit/common/__init__.py,sha256=yDoMJDKj-xjTGl7U1YI59KpWxiOV65HSiUulgO8xdTA,277
|
@@ -132,7 +133,7 @@ beamlit/common/generate.py,sha256=LtdCju_QayRS4lZrrb_0VHqWWvTcv4Mbf-iV1TB_Qko,75
|
|
132
133
|
beamlit/common/instrumentation.py,sha256=MsBDfFcMYqGDiHHj4j5hLHE4EWxZExkhmCeFS3SKzJY,3181
|
133
134
|
beamlit/common/logger.py,sha256=VFRbaZh93n8ZGugeeYKe88IP2nI3g2JNa7XN4j8wVJE,1116
|
134
135
|
beamlit/common/secrets.py,sha256=sid81bOe3LflkMKDHwBsBs9nIju8bp5-v9qU9gkyNMc,212
|
135
|
-
beamlit/common/settings.py,sha256=
|
136
|
+
beamlit/common/settings.py,sha256=uge6-VTioSILA9lgPpKc5V7MaSEMuHYHfCQhwdqHteE,5831
|
136
137
|
beamlit/common/utils.py,sha256=jouz5igBvT37Xn_e94-foCHyQczVim-UzVcoIF6RWJ4,657
|
137
138
|
beamlit/deploy/__init__.py,sha256=GS7l7Jtm2yKs7iNLKcfjYO-rAhUzggQ3xiYSf3oxLBY,91
|
138
139
|
beamlit/deploy/deploy.py,sha256=rXpiAqlO36Ul1eadBEiwiil-6R2DkbaYHzw-qcqZ0g4,9183
|
@@ -147,7 +148,7 @@ beamlit/functions/github/kit/pull_request.py,sha256=wQVeRBakiqu-2ouflO8p1z7D5u07
|
|
147
148
|
beamlit/functions/math/__init__.py,sha256=wie4WME8jT-WpFRrtu-lDlHW31Mg6K2cwstjkUdLF3o,43
|
148
149
|
beamlit/functions/math/math.py,sha256=CpoLJGwuvwCPGnVC8k9GYuIyvfUYPDQHKlZg3cx-z-A,1049
|
149
150
|
beamlit/functions/mcp/mcp.py,sha256=uGqNOwEgIKdvtVPmCf9Nf_YI_k7zioLvc6jVOpszrg4,4104
|
150
|
-
beamlit/functions/remote/remote.py,sha256=
|
151
|
+
beamlit/functions/remote/remote.py,sha256=Cfmml8yO3tlszLN2rtwp4FpipLabNSjdRN4Q29sDweQ,3836
|
151
152
|
beamlit/functions/search/__init__.py,sha256=5NAthQ9PBwrkNg1FpLRx4flauvv0HyWuwaVS589c1Pw,49
|
152
153
|
beamlit/functions/search/search.py,sha256=8s9ECltq7YE17j6rTxb12uY2EQY4_eTLHmwlIMThI0w,515
|
153
154
|
beamlit/models/__init__.py,sha256=O16oX1-oBJqB5LZEHAfu_hZZZh6_PX2LqZpVl4fNQRs,7730
|
@@ -253,6 +254,6 @@ beamlit/serve/app.py,sha256=OpwPjRdyHZK6J-ziPwhiRDGGa2mvCrFVcBFE6alJVOM,3071
|
|
253
254
|
beamlit/serve/middlewares/__init__.py,sha256=1dVmnOmhAQWvWktqHkKSIX-YoF6fmMU8xkUQuhg_rJU,148
|
254
255
|
beamlit/serve/middlewares/accesslog.py,sha256=Mu4T4_9OvHybjA0ApzZFpgi2C8f3X1NbUk-76v634XM,631
|
255
256
|
beamlit/serve/middlewares/processtime.py,sha256=lDAaIasZ4bwvN-HKHvZpaD9r-yrkVNZYx4abvbjbrCg,411
|
256
|
-
beamlit-0.0.
|
257
|
-
beamlit-0.0.
|
258
|
-
beamlit-0.0.
|
257
|
+
beamlit-0.0.29rc26.dist-info/METADATA,sha256=q6aJeKGzSLnVJtuVjAEFGM7wXesSc4-Vre2neU3FPts,2405
|
258
|
+
beamlit-0.0.29rc26.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
259
|
+
beamlit-0.0.29rc26.dist-info/RECORD,,
|
File without changes
|