beamlit 0.0.31rc42__py3-none-any.whl → 0.0.33__py3-none-any.whl
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.
- 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
|