beamlit 0.0.31rc42__py3-none-any.whl → 0.0.33__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- beamlit/agents/decorator.py +32 -19
- beamlit/common/__init__.py +3 -2
- beamlit/common/settings.py +4 -63
- beamlit/common/slugify.py +2 -0
- beamlit/deploy/deploy.py +2 -3
- beamlit/functions/decorator.py +12 -62
- beamlit/serve/app.py +2 -4
- {beamlit-0.0.31rc42.dist-info → beamlit-0.0.33.dist-info}/METADATA +1 -1
- {beamlit-0.0.31rc42.dist-info → beamlit-0.0.33.dist-info}/RECORD +10 -10
- beamlit/common/generate.py +0 -196
- {beamlit-0.0.31rc42.dist-info → beamlit-0.0.33.dist-info}/WHEEL +0 -0
beamlit/agents/decorator.py
CHANGED
@@ -6,13 +6,15 @@ import importlib
|
|
6
6
|
import os
|
7
7
|
from logging import getLogger
|
8
8
|
|
9
|
-
from langchain_core.tools import
|
9
|
+
from langchain_core.tools import StructuredTool
|
10
10
|
from langgraph.checkpoint.memory import MemorySaver
|
11
11
|
from langgraph.prebuilt import create_react_agent
|
12
|
+
from langchain_core.tools.base import create_schema_from_function
|
12
13
|
|
13
14
|
from beamlit.api.models import get_model
|
14
15
|
from beamlit.authentication import new_client
|
15
|
-
from beamlit.common
|
16
|
+
from beamlit.common import slugify
|
17
|
+
from beamlit.common.settings import get_settings, init
|
16
18
|
from beamlit.errors import UnexpectedStatus
|
17
19
|
from beamlit.functions.mcp.mcp import MCPClient, MCPToolkit
|
18
20
|
from beamlit.functions.remote.remote import RemoteToolkit
|
@@ -22,9 +24,10 @@ from .chain import ChainToolkit
|
|
22
24
|
from .chat import get_chat_model
|
23
25
|
|
24
26
|
|
25
|
-
def get_functions(dir="src/functions", from_decorator="function", remote_functions_empty=True):
|
27
|
+
def get_functions(client, dir="src/functions", from_decorator="function", remote_functions_empty=True):
|
26
28
|
functions = []
|
27
29
|
logger = getLogger(__name__)
|
30
|
+
settings = get_settings()
|
28
31
|
|
29
32
|
# Walk through all Python files in functions directory and subdirectories
|
30
33
|
if not os.path.exists(dir):
|
@@ -73,8 +76,9 @@ def get_functions(dir="src/functions", from_decorator="function", remote_functio
|
|
73
76
|
keyword.value, ast.Constant
|
74
77
|
):
|
75
78
|
is_kit = keyword.value.value
|
76
|
-
if is_kit:
|
79
|
+
if is_kit and not settings.remote:
|
77
80
|
kit_functions = get_functions(
|
81
|
+
client,
|
78
82
|
dir=os.path.join(root),
|
79
83
|
from_decorator="kit",
|
80
84
|
remote_functions_empty=remote_functions_empty,
|
@@ -84,23 +88,30 @@ def get_functions(dir="src/functions", from_decorator="function", remote_functio
|
|
84
88
|
# Get the decorated function
|
85
89
|
if not is_kit and hasattr(module, func_name):
|
86
90
|
func = getattr(module, func_name)
|
87
|
-
if
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
description=func.__doc__,
|
92
|
-
func=func,
|
93
|
-
coroutine=func,
|
94
|
-
)
|
95
|
-
)
|
91
|
+
if settings.remote:
|
92
|
+
toolkit = RemoteToolkit(client, slugify(func.__name__))
|
93
|
+
toolkit.initialize()
|
94
|
+
functions.extend(toolkit.get_tools())
|
96
95
|
else:
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
96
|
+
if asyncio.iscoroutinefunction(func):
|
97
|
+
functions.append(
|
98
|
+
StructuredTool(
|
99
|
+
name=func.__name__,
|
100
|
+
description=func.__doc__,
|
101
|
+
func=func,
|
102
|
+
coroutine=func,
|
103
|
+
args_schema=create_schema_from_function(func.__name__, func)
|
104
|
+
)
|
105
|
+
)
|
106
|
+
else:
|
107
|
+
functions.append(
|
108
|
+
StructuredTool(
|
109
|
+
name=func.__name__,
|
110
|
+
description=func.__doc__,
|
111
|
+
func=func,
|
112
|
+
args_schema=create_schema_from_function(func.__name__, func)
|
113
|
+
)
|
102
114
|
)
|
103
|
-
)
|
104
115
|
except Exception as e:
|
105
116
|
logger.warning(f"Error processing {file_path}: {e!s}")
|
106
117
|
return functions
|
@@ -139,9 +150,11 @@ def agent(
|
|
139
150
|
|
140
151
|
# Initialize functions array to store decorated functions
|
141
152
|
functions = get_functions(
|
153
|
+
client,
|
142
154
|
dir=settings.agent.functions_directory,
|
143
155
|
remote_functions_empty=not remote_functions,
|
144
156
|
)
|
157
|
+
|
145
158
|
settings.agent.functions = functions
|
146
159
|
|
147
160
|
if agent is not None:
|
beamlit/common/__init__.py
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
from .error import HTTPError
|
2
2
|
from .logger import init as init_logger
|
3
3
|
from .secrets import Secret
|
4
|
-
from .settings import Settings, get_settings, init
|
4
|
+
from .settings import Settings, get_settings, init
|
5
|
+
from .slugify import slugify
|
5
6
|
from .utils import copy_folder
|
6
7
|
|
7
8
|
__all__ = [
|
8
9
|
"Secret",
|
9
10
|
"Settings",
|
10
11
|
"get_settings",
|
11
|
-
"init_agent",
|
12
12
|
"init",
|
13
13
|
"copy_folder",
|
14
14
|
"init_logger",
|
15
15
|
"HTTPError",
|
16
|
+
"slugify"
|
16
17
|
]
|
beamlit/common/settings.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
import os
|
2
|
-
from logging import getLogger
|
3
2
|
from typing import Tuple, Type, Union
|
4
3
|
|
5
4
|
from langchain_core.language_models.chat_models import BaseChatModel
|
@@ -12,22 +11,17 @@ from pydantic_settings import (
|
|
12
11
|
YamlConfigSettingsSource,
|
13
12
|
)
|
14
13
|
|
15
|
-
from beamlit.api.agents import get_agent
|
16
|
-
from beamlit.api.functions import get_function
|
17
|
-
from beamlit.api.models import get_model
|
18
|
-
from beamlit.client import AuthenticatedClient
|
19
14
|
from beamlit.common.logger import init as init_logger
|
20
15
|
from beamlit.models import Agent, Function, Model
|
21
|
-
from beamlit.types import UNSET, Unset
|
22
16
|
|
23
17
|
global SETTINGS
|
24
18
|
SETTINGS = None
|
25
19
|
|
26
20
|
class SettingsAgent(BaseSettings):
|
27
|
-
agent: Union[None, CompiledGraph
|
28
|
-
chain: Union[
|
29
|
-
model: Union[
|
30
|
-
functions: Union[
|
21
|
+
agent: Union[None, CompiledGraph] = None
|
22
|
+
chain: Union[None, list[Agent]] = None
|
23
|
+
model: Union[None, Model] = None
|
24
|
+
functions: Union[None, list[Function]] = None
|
31
25
|
functions_directory: str = Field(default="src/functions")
|
32
26
|
chat_model: Union[None, BaseChatModel] = None
|
33
27
|
module: str = Field(default="main.main")
|
@@ -100,59 +94,6 @@ class Settings(BaseSettings):
|
|
100
94
|
def get_settings() -> Settings:
|
101
95
|
return SETTINGS
|
102
96
|
|
103
|
-
|
104
|
-
def init_agent(
|
105
|
-
client: AuthenticatedClient,
|
106
|
-
destination: str = f"{os.getcwd()}/src/beamlit_generated.py",
|
107
|
-
):
|
108
|
-
from beamlit.common.generate import generate
|
109
|
-
|
110
|
-
logger = getLogger(__name__)
|
111
|
-
settings = get_settings()
|
112
|
-
# Init configuration from environment variables
|
113
|
-
if settings.agent.functions or settings.agent.chain:
|
114
|
-
return
|
115
|
-
|
116
|
-
# Init configuration from beamlit control plane
|
117
|
-
name = settings.name
|
118
|
-
env = settings.environment
|
119
|
-
|
120
|
-
agent = get_agent.sync(name, environment=env, client=client)
|
121
|
-
if not agent:
|
122
|
-
raise ValueError(f"Agent {name} not found")
|
123
|
-
functions: list[Function] = []
|
124
|
-
agents_chain: list[Agent] = []
|
125
|
-
if agent.spec.functions:
|
126
|
-
for function in agent.spec.functions:
|
127
|
-
function = get_function.sync(function, environment=env, client=client)
|
128
|
-
if function:
|
129
|
-
functions.append(function)
|
130
|
-
settings.agent.functions = functions
|
131
|
-
|
132
|
-
if agent.spec.agentChain:
|
133
|
-
for chain in agent.spec.agentChain:
|
134
|
-
if chain.enabled:
|
135
|
-
agentChain = get_agent.sync(chain.name, environment=env, client=client)
|
136
|
-
if chain.description:
|
137
|
-
agentChain.spec.description = chain.description
|
138
|
-
agents_chain.append(agentChain)
|
139
|
-
settings.agent.chain = agents_chain
|
140
|
-
if agent.spec.model:
|
141
|
-
model = get_model.sync(agent.spec.model, environment=env, client=client)
|
142
|
-
settings.agent.model = model
|
143
|
-
|
144
|
-
content_generate = generate(destination, dry_run=True)
|
145
|
-
compared_content = None
|
146
|
-
if os.path.exists(destination):
|
147
|
-
compared_content = open(destination).read()
|
148
|
-
|
149
|
-
if not os.path.exists(destination) or (
|
150
|
-
compared_content and content_generate != compared_content
|
151
|
-
):
|
152
|
-
logger.info("Generating agent code")
|
153
|
-
generate(destination)
|
154
|
-
|
155
|
-
|
156
97
|
def init() -> Settings:
|
157
98
|
"""Parse the beamlit.yaml file to get configurations."""
|
158
99
|
from beamlit.authentication.credentials import current_context
|
beamlit/deploy/deploy.py
CHANGED
@@ -6,6 +6,7 @@ import uuid
|
|
6
6
|
from logging import getLogger
|
7
7
|
from typing import Literal
|
8
8
|
|
9
|
+
from beamlit.common import slugify
|
9
10
|
from beamlit.common.settings import Settings, get_settings, init
|
10
11
|
from beamlit.models import (
|
11
12
|
Agent,
|
@@ -24,8 +25,6 @@ sys.path.insert(0, os.getcwd())
|
|
24
25
|
sys.path.insert(0, os.path.join(os.getcwd(), "src"))
|
25
26
|
|
26
27
|
random_id = str(uuid.uuid4())[:8]
|
27
|
-
def slugify(name: str) -> str:
|
28
|
-
return name.lower().replace(" ", "-").replace("_", "-")
|
29
28
|
|
30
29
|
def get_runtime_image(type: str, name: str) -> str:
|
31
30
|
settings = get_settings()
|
@@ -130,7 +129,7 @@ metadata:
|
|
130
129
|
spec:
|
131
130
|
enabled: true
|
132
131
|
policies: [{", ".join(agent.spec.policies or [])}]
|
133
|
-
functions: [{", ".join([f"{function.metadata.name}" for (_, function) in functions])}]
|
132
|
+
functions: [{", ".join([f"{slugify(function.metadata.name)}" for (_, function) in functions])}]
|
134
133
|
agentChain: {format_agent_chain(agent.spec.agent_chain)}
|
135
134
|
model: {agent.spec.model}
|
136
135
|
runtime:
|
beamlit/functions/decorator.py
CHANGED
@@ -1,62 +1,15 @@
|
|
1
1
|
"""Decorators for creating function tools with Beamlit and LangChain integration."""
|
2
|
-
|
3
|
-
import
|
2
|
+
import asyncio
|
3
|
+
import functools
|
4
4
|
from collections.abc import Callable
|
5
5
|
from logging import getLogger
|
6
6
|
|
7
|
-
from
|
7
|
+
from fastapi import Request
|
8
8
|
|
9
|
-
from beamlit.authentication import new_client
|
10
|
-
from beamlit.common.settings import get_settings
|
11
9
|
from beamlit.models import Function, FunctionKit
|
12
|
-
from beamlit.run import RunClient
|
13
10
|
|
14
11
|
logger = getLogger(__name__)
|
15
12
|
|
16
|
-
|
17
|
-
def get_remote_function(func: Callable, function: Function):
|
18
|
-
settings = get_settings()
|
19
|
-
name = (function and function.metadata and function.metadata.name) or func.__name__
|
20
|
-
|
21
|
-
def _partial(*args, **kwargs):
|
22
|
-
# Get function signature parameters
|
23
|
-
try:
|
24
|
-
client = new_client()
|
25
|
-
run_client = RunClient(client)
|
26
|
-
logger.debug(
|
27
|
-
f"Calling remote function: NAME={name}"
|
28
|
-
f" PARAMS={kwargs} ENVIRONMENT={settings.environment}"
|
29
|
-
)
|
30
|
-
response = run_client.run(
|
31
|
-
resource_type="function",
|
32
|
-
resource_name=name,
|
33
|
-
environment=settings.environment,
|
34
|
-
method="POST",
|
35
|
-
headers={"Content-Type": "application/json"},
|
36
|
-
data=json.dumps(kwargs),
|
37
|
-
)
|
38
|
-
content = response.text
|
39
|
-
if response.status_code >= 400:
|
40
|
-
content = f"{response.status_code}:{response.text}"
|
41
|
-
logger.error(f"Error calling remote function: {content}")
|
42
|
-
return f"Error calling remote function: {content}"
|
43
|
-
logger.debug(
|
44
|
-
f"Response from remote function: NAME={name}"
|
45
|
-
f" RESPONSE={content} ENVIRONMENT={settings.environment}"
|
46
|
-
)
|
47
|
-
if response.headers.get("content-type") == "application/json":
|
48
|
-
return response.json()
|
49
|
-
return content
|
50
|
-
except Exception as e:
|
51
|
-
logger.error(f"Error calling function {name}: {e}")
|
52
|
-
raise e
|
53
|
-
|
54
|
-
remote_func = _partial
|
55
|
-
remote_func.__name__ = func.__name__
|
56
|
-
remote_func.__doc__ = func.__doc__
|
57
|
-
return remote_func
|
58
|
-
|
59
|
-
|
60
13
|
def kit(bl_kit: FunctionKit = None, **kwargs: dict) -> Callable:
|
61
14
|
"""Create function tools with Beamlit and LangChain integration."""
|
62
15
|
|
@@ -70,26 +23,23 @@ def kit(bl_kit: FunctionKit = None, **kwargs: dict) -> Callable:
|
|
70
23
|
|
71
24
|
def function(*args, function: Function | dict = None, kit=False, **kwargs: dict) -> Callable:
|
72
25
|
"""Create function tools with Beamlit and LangChain integration."""
|
73
|
-
settings = get_settings()
|
74
26
|
if function is not None and not isinstance(function, dict):
|
75
27
|
raise Exception(
|
76
28
|
'function must be a dictionary, example: @function(function={"metadata": {"name": "my_function"}})'
|
77
29
|
)
|
78
30
|
if isinstance(function, dict):
|
79
31
|
function = Function(**function)
|
80
|
-
|
32
|
+
|
81
33
|
def wrapper(func: Callable) -> Callable:
|
82
34
|
if function and not func.__doc__ and function.spec and function.spec.description:
|
83
35
|
func.__doc__ = function.spec.description
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
return remote_func
|
93
|
-
return func
|
36
|
+
|
37
|
+
@functools.wraps(func)
|
38
|
+
async def wrapped(*args, **kwargs):
|
39
|
+
if len(args) > 0 and isinstance(args[0], Request):
|
40
|
+
body = await args[0].json()
|
41
|
+
args = [body.get(param) for param in func.__code__.co_varnames[:func.__code__.co_argcount]]
|
42
|
+
return await func(*args, **kwargs) if asyncio.iscoroutinefunction(func) else func(*args, **kwargs)
|
43
|
+
return wrapped
|
94
44
|
|
95
45
|
return wrapper
|
beamlit/serve/app.py
CHANGED
@@ -71,13 +71,11 @@ async def root(request: Request):
|
|
71
71
|
settings = get_settings()
|
72
72
|
logger = getLogger(__name__)
|
73
73
|
try:
|
74
|
-
body = await request.json()
|
75
|
-
|
76
74
|
original_func = getattr(func, "__wrapped__", func)
|
77
75
|
if asyncio.iscoroutinefunction(func) or asyncio.iscoroutinefunction(original_func):
|
78
|
-
response = await func(
|
76
|
+
response = await func(request)
|
79
77
|
else:
|
80
|
-
response = func(
|
78
|
+
response = func(request)
|
81
79
|
|
82
80
|
if isinstance(response, Response):
|
83
81
|
return response
|
@@ -7,7 +7,7 @@ beamlit/types.py,sha256=E1hhDh_zXfsSQ0NCt9-uw90_Mr5iIlsdfnfvxv5HarU,1005
|
|
7
7
|
beamlit/agents/__init__.py,sha256=nf1iwQwGtCG6nDqyVhxfWoqR6dv6X3bvSpCeqkTCFaM,101
|
8
8
|
beamlit/agents/chain.py,sha256=vfCjiFHuu02uTTGicxMlFzjyICQkIjpXrBGs-7uJEsg,2826
|
9
9
|
beamlit/agents/chat.py,sha256=gVyv4FGBdQTDhdutX8l64OUNa6Fdqaw4eCfEDRH0IPQ,3558
|
10
|
-
beamlit/agents/decorator.py,sha256=
|
10
|
+
beamlit/agents/decorator.py,sha256=n3sETKu8V2g3GDJ0f17kUowyqaRJvpg3n_BGRRVuNGY,10619
|
11
11
|
beamlit/api/__init__.py,sha256=zTSiG_ujSjAqWPyc435YXaX9XTlpMjiJWBbV-f-YtdA,45
|
12
12
|
beamlit/api/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
beamlit/api/agents/create_agent.py,sha256=t5Pr62My2EhQlcIY71MrI73-0_q5Djr3a_Ybt9MIiQQ,3587
|
@@ -128,20 +128,20 @@ beamlit/authentication/authentication.py,sha256=ODQCc00RvCOZNaiGG5ctylNnE-JVCuge
|
|
128
128
|
beamlit/authentication/clientcredentials.py,sha256=cxZPPu--CgizwqX0pdfFQ91gJt1EFKwyy-aBB_dXX7I,3990
|
129
129
|
beamlit/authentication/credentials.py,sha256=p_1xenabCbQuRz7BiFk7oTK4uCxAt_zoyku5o-jcKGE,5343
|
130
130
|
beamlit/authentication/device_mode.py,sha256=tmr22gllKOZwBRub_QjF5pYa425x-nE8tQNpZ_EGR6g,3644
|
131
|
-
beamlit/common/__init__.py,sha256=
|
131
|
+
beamlit/common/__init__.py,sha256=saX5X3hRCJ9erSlXuSkZ2VGgquvpgdcofAU_9sM4bCE,354
|
132
132
|
beamlit/common/error.py,sha256=f9oJDFxhoHK-vpjxBgEp0NwWIk0N_THPemUI7uQxVzU,270
|
133
|
-
beamlit/common/generate.py,sha256=LtdCju_QayRS4lZrrb_0VHqWWvTcv4Mbf-iV1TB_Qko,7522
|
134
133
|
beamlit/common/instrumentation.py,sha256=GVYeat7qCcqzDoKSYig3s8ZCC172R9JiQIr3Evv3kik,4293
|
135
134
|
beamlit/common/logger.py,sha256=nN_dSOl4bs13QU3Rod-w3e3jYOnlSrHx3_bs-ACY6Aw,1115
|
136
135
|
beamlit/common/secrets.py,sha256=sid81bOe3LflkMKDHwBsBs9nIju8bp5-v9qU9gkyNMc,212
|
137
|
-
beamlit/common/settings.py,sha256=
|
136
|
+
beamlit/common/settings.py,sha256=b2rvby-ufG3M0AB1ReoWFM-1EzF1LaE-gbokO9HvQDI,3810
|
137
|
+
beamlit/common/slugify.py,sha256=nR29r37IdWS2i44ZC6ZsXRgqKPYmvMGtFQ7BuIQUTlc,90
|
138
138
|
beamlit/common/utils.py,sha256=jouz5igBvT37Xn_e94-foCHyQczVim-UzVcoIF6RWJ4,657
|
139
139
|
beamlit/deploy/__init__.py,sha256=GS7l7Jtm2yKs7iNLKcfjYO-rAhUzggQ3xiYSf3oxLBY,91
|
140
|
-
beamlit/deploy/deploy.py,sha256=
|
140
|
+
beamlit/deploy/deploy.py,sha256=YKY1iN0ZofQr_n9efvDJ5pK9HpyLZO9wyHmh8W9PAaE,9889
|
141
141
|
beamlit/deploy/format.py,sha256=PJ8kU7Y1pwiS3tqqyvFaag9LO3jju-4ua574163VPk4,1820
|
142
142
|
beamlit/deploy/parser.py,sha256=Ga0poCZkoRnuTw082QnTcNGCBJncoRAnVsn8-1FsaJE,6907
|
143
143
|
beamlit/functions/__init__.py,sha256=_RPG1Bfg54JGdIPnViAU6n9zD7E1cDNsdXi8oYGskzE,138
|
144
|
-
beamlit/functions/decorator.py,sha256=
|
144
|
+
beamlit/functions/decorator.py,sha256=ZtSQsPLI70WKwi2jPhA7DaqREQUINpqt9BDVugeV_sg,1714
|
145
145
|
beamlit/functions/github/__init__.py,sha256=gYnUkeegukOfbymdabuuJkScvH-_ZJygX05BoqkPn0o,49
|
146
146
|
beamlit/functions/github/github.py,sha256=FajzLCNkpXcwfgnC0l9rOGT2eSPLCz8-qrMzK9N_ZNc,598
|
147
147
|
beamlit/functions/github/kit/__init__.py,sha256=jBwPqZv6C23_utukohxqXZwrlicNlI7PYPUj0Den7Cw,136
|
@@ -252,10 +252,10 @@ beamlit/models/websocket_channel.py,sha256=jg3vN7yS_oOIwGtndtIUr1LsyEA58RXLXahqS
|
|
252
252
|
beamlit/models/workspace.py,sha256=l__bIpbA4oJvxXo7UbEoCcqkvu9MiNt5aXXpZ3bgwHg,4309
|
253
253
|
beamlit/models/workspace_labels.py,sha256=WbnUY6eCTkUNdY7hhhSF-KQCl8fWFfkCf7hzCTiNp4A,1246
|
254
254
|
beamlit/models/workspace_user.py,sha256=70CcifQWYbeWG7TDui4pblTzUe5sVK0AS19vNCzKE8g,3423
|
255
|
-
beamlit/serve/app.py,sha256=
|
255
|
+
beamlit/serve/app.py,sha256=DXWxQoMeuA5FYvBMyLrP94OEWQbwLf4GZk3I9fkwSPA,3523
|
256
256
|
beamlit/serve/middlewares/__init__.py,sha256=1dVmnOmhAQWvWktqHkKSIX-YoF6fmMU8xkUQuhg_rJU,148
|
257
257
|
beamlit/serve/middlewares/accesslog.py,sha256=Mu4T4_9OvHybjA0ApzZFpgi2C8f3X1NbUk-76v634XM,631
|
258
258
|
beamlit/serve/middlewares/processtime.py,sha256=lDAaIasZ4bwvN-HKHvZpaD9r-yrkVNZYx4abvbjbrCg,411
|
259
|
-
beamlit-0.0.
|
260
|
-
beamlit-0.0.
|
261
|
-
beamlit-0.0.
|
259
|
+
beamlit-0.0.33.dist-info/METADATA,sha256=4AMW5iTcsR-ZCtdCDjbHpt7mN-1OFd_Haj7dOWztBFw,2401
|
260
|
+
beamlit-0.0.33.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
261
|
+
beamlit-0.0.33.dist-info/RECORD,,
|
beamlit/common/generate.py
DELETED
@@ -1,196 +0,0 @@
|
|
1
|
-
from typing import Tuple
|
2
|
-
|
3
|
-
from beamlit.common.settings import Settings, get_settings
|
4
|
-
from beamlit.models import Agent, Function, FunctionMetadata, FunctionSpec
|
5
|
-
from beamlit.models.function_kit import FunctionKit
|
6
|
-
|
7
|
-
|
8
|
-
def get_titles_name(name: str) -> str:
|
9
|
-
return name.title().replace("-", "").replace("_", "")
|
10
|
-
|
11
|
-
|
12
|
-
def generate_kit_function_code(
|
13
|
-
settings: Settings, function: Function, kit: FunctionKit
|
14
|
-
) -> Tuple[str, str]:
|
15
|
-
export_code = ""
|
16
|
-
code = ""
|
17
|
-
for kit in kit:
|
18
|
-
fn = Function(
|
19
|
-
metadata=FunctionMetadata(
|
20
|
-
name=kit.name,
|
21
|
-
workspace=settings.workspace,
|
22
|
-
environment=settings.environment,
|
23
|
-
),
|
24
|
-
spec=FunctionSpec(
|
25
|
-
parameters=kit.parameters,
|
26
|
-
description=kit.description,
|
27
|
-
),
|
28
|
-
)
|
29
|
-
new_code, export = generate_function_code(
|
30
|
-
settings, fn, force_name_in_endpoint=function.metadata.name, kit=True
|
31
|
-
)
|
32
|
-
code += new_code
|
33
|
-
export_code += export
|
34
|
-
return code, export_code
|
35
|
-
|
36
|
-
|
37
|
-
def generate_function_code(
|
38
|
-
settings: Settings,
|
39
|
-
function: Function,
|
40
|
-
force_name_in_endpoint: str = "",
|
41
|
-
kit: bool = False,
|
42
|
-
) -> Tuple[str, str]:
|
43
|
-
name = get_titles_name(function.metadata.name)
|
44
|
-
if function.spec.parameters and len(function.spec.parameters) > 0:
|
45
|
-
args_list = ", ".join(f"{param.name}: str" for param in function.spec.parameters)
|
46
|
-
args_list += ", "
|
47
|
-
else:
|
48
|
-
args_list = ""
|
49
|
-
args_schema = ""
|
50
|
-
if function.spec.parameters:
|
51
|
-
for param in function.spec.parameters:
|
52
|
-
args_schema += f'{param.name}: str = Field(description="""{param.description}""")\n '
|
53
|
-
if len(args_schema) == 0:
|
54
|
-
args_schema = "pass"
|
55
|
-
|
56
|
-
# TODO: add return direct in function configuration
|
57
|
-
return_direct = False
|
58
|
-
endpoint_name = force_name_in_endpoint or function.metadata.name
|
59
|
-
body = "{}"
|
60
|
-
if function.spec.parameters:
|
61
|
-
body = f'{", ".join(f'"{param.name}": {param.name}' for param in function.spec.parameters)}'
|
62
|
-
if kit is True:
|
63
|
-
has_name = False
|
64
|
-
if function.spec.parameters:
|
65
|
-
for param in function.spec.parameters:
|
66
|
-
if param.name == "name":
|
67
|
-
has_name = True
|
68
|
-
break
|
69
|
-
if not has_name:
|
70
|
-
if len(body) > 0:
|
71
|
-
body += ", "
|
72
|
-
body += f'"name": "{function.metadata.name}"'
|
73
|
-
return (
|
74
|
-
f'''
|
75
|
-
|
76
|
-
class Beamlit{name}Input(BaseModel):
|
77
|
-
{args_schema}
|
78
|
-
|
79
|
-
class Beamlit{name}(BaseTool):
|
80
|
-
name: str = "beamlit_{function.metadata.name.replace("-", "_")}"
|
81
|
-
description: str = """{function.spec.description}"""
|
82
|
-
args_schema: Type[BaseModel] = Beamlit{name}Input
|
83
|
-
|
84
|
-
response_format: Literal["content_and_artifact"] = "content_and_artifact"
|
85
|
-
return_direct: bool = {return_direct}
|
86
|
-
|
87
|
-
def _run(self, {args_list} run_manager: Optional[CallbackManagerForToolRun] = None) -> Tuple[Union[List[Dict[str, str]], str], Dict]:
|
88
|
-
try:
|
89
|
-
params = self.metadata.get("params", {{}})
|
90
|
-
response = run_client.run("function", "{endpoint_name}", settings.environment, "POST", json={{{body}}})
|
91
|
-
if response.status_code >= 400:
|
92
|
-
logger.error(f"Failed to run function {name}, {{response.status_code}}::{{response.text}}")
|
93
|
-
raise Exception(f"Failed to run function {name}, {{response.status_code}}::{{response.text}}")
|
94
|
-
return response.json(), {{}}
|
95
|
-
except Exception as e:
|
96
|
-
return repr(e), {{}}
|
97
|
-
''',
|
98
|
-
f"Beamlit{get_titles_name(function.metadata.name)},",
|
99
|
-
)
|
100
|
-
|
101
|
-
|
102
|
-
def generate_chain_code(settings: Settings, agent: Agent) -> Tuple[str, str]:
|
103
|
-
name = get_titles_name(agent.metadata.name)
|
104
|
-
# TODO: add return direct in agent configuration
|
105
|
-
return_direct = False
|
106
|
-
return (
|
107
|
-
f'''
|
108
|
-
class BeamlitChain{name}Input(BaseModel):
|
109
|
-
input: str = Field(description='{agent.spec.description}')
|
110
|
-
|
111
|
-
class BeamlitChain{name}(BaseTool):
|
112
|
-
name: str = "beamlit_chain_{agent.metadata.name.replace("-", "_")}"
|
113
|
-
description: str = """{agent.spec.description}"""
|
114
|
-
args_schema: Type[BaseModel] = BeamlitChain{name}Input
|
115
|
-
|
116
|
-
response_format: Literal["content_and_artifact"] = "content_and_artifact"
|
117
|
-
return_direct: bool = {return_direct}
|
118
|
-
|
119
|
-
def _run(
|
120
|
-
self,
|
121
|
-
input: str,
|
122
|
-
run_manager: Optional[CallbackManagerForToolRun] = None,
|
123
|
-
) -> Tuple[Union[List[Dict[str, str]], str], Dict]:
|
124
|
-
try:
|
125
|
-
params = self.metadata.get("params", {{}})
|
126
|
-
response = run_client.run("agent", "{agent.metadata.name}", settings.environment, "POST", json={{"input": input}})
|
127
|
-
if response.status_code >= 400:
|
128
|
-
logger.error(f"Failed to run tool {agent.metadata.name}, {{response.status_code}}::{{response.text}}")
|
129
|
-
raise Exception(f"Failed to run tool {agent.metadata.name}, {{response.status_code}}::{{response.text}}")
|
130
|
-
if response.headers.get("Content-Type") == "application/json":
|
131
|
-
return response.json(), {{}}
|
132
|
-
else:
|
133
|
-
return response.text, {{}}
|
134
|
-
except Exception as e:
|
135
|
-
return repr(e), {{}}
|
136
|
-
''',
|
137
|
-
f"BeamlitChain{name},",
|
138
|
-
)
|
139
|
-
|
140
|
-
|
141
|
-
def generate(destination: str, dry_run: bool = False):
|
142
|
-
imports = """from logging import getLogger
|
143
|
-
from typing import Dict, List, Literal, Optional, Tuple, Type, Union
|
144
|
-
|
145
|
-
from langchain_core.callbacks import CallbackManagerForToolRun
|
146
|
-
from langchain_core.tools import BaseTool
|
147
|
-
from pydantic import BaseModel, Field
|
148
|
-
from beamlit.authentication import (RunClientWithCredentials,
|
149
|
-
load_credentials_from_settings,
|
150
|
-
new_client_with_credentials)
|
151
|
-
from beamlit.common.settings import get_settings
|
152
|
-
from beamlit.run import RunClient
|
153
|
-
|
154
|
-
logger = getLogger(__name__)
|
155
|
-
settings = get_settings()
|
156
|
-
credentials = load_credentials_from_settings(settings)
|
157
|
-
|
158
|
-
client_config = RunClientWithCredentials(
|
159
|
-
credentials=credentials,
|
160
|
-
workspace=settings.workspace,
|
161
|
-
)
|
162
|
-
client = new_client_with_credentials(client_config)
|
163
|
-
run_client = RunClient(client=client)
|
164
|
-
"""
|
165
|
-
settings = get_settings()
|
166
|
-
export_code = "\n\nfunctions = ["
|
167
|
-
export_chain = "\n\nchains = ["
|
168
|
-
code = imports
|
169
|
-
if settings.agent.functions and len(settings.agent.functions) > 0:
|
170
|
-
for function_config in settings.agent.functions:
|
171
|
-
if function_config.spec.kit and len(function_config.spec.kit) > 0:
|
172
|
-
new_code, export = generate_kit_function_code(
|
173
|
-
settings, function_config, function_config.spec.kit
|
174
|
-
)
|
175
|
-
code += new_code
|
176
|
-
export_code += export
|
177
|
-
else:
|
178
|
-
new_code, export = generate_function_code(settings, function_config)
|
179
|
-
code += new_code
|
180
|
-
export_code += export
|
181
|
-
if settings.agent.chain and len(settings.agent.chain) > 0:
|
182
|
-
for agent in settings.agent.chain:
|
183
|
-
new_code, export = generate_chain_code(settings, agent)
|
184
|
-
code += new_code
|
185
|
-
export_chain += export
|
186
|
-
if settings.agent.functions and len(settings.agent.functions) > 0:
|
187
|
-
export_code = export_code[:-1]
|
188
|
-
export_code += "]"
|
189
|
-
if settings.agent.chain and len(settings.agent.chain) > 0:
|
190
|
-
export_chain = export_chain[:-1]
|
191
|
-
export_chain += "]"
|
192
|
-
content = code + export_code + export_chain
|
193
|
-
if not dry_run:
|
194
|
-
with open(destination, "w") as f:
|
195
|
-
f.write(content)
|
196
|
-
return content
|
File without changes
|