llama-deploy-appserver 0.2.7a1__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.
- llama_deploy/appserver/__init__.py +0 -0
- llama_deploy/appserver/__main__.py +14 -0
- llama_deploy/appserver/app.py +49 -0
- llama_deploy/appserver/bootstrap.py +43 -0
- llama_deploy/appserver/client/__init__.py +3 -0
- llama_deploy/appserver/client/base.py +30 -0
- llama_deploy/appserver/client/client.py +49 -0
- llama_deploy/appserver/client/models/__init__.py +4 -0
- llama_deploy/appserver/client/models/apiserver.py +356 -0
- llama_deploy/appserver/client/models/model.py +82 -0
- llama_deploy/appserver/deployment.py +495 -0
- llama_deploy/appserver/deployment_config_parser.py +133 -0
- llama_deploy/appserver/routers/__init__.py +4 -0
- llama_deploy/appserver/routers/deployments.py +433 -0
- llama_deploy/appserver/routers/status.py +40 -0
- llama_deploy/appserver/run_autodeploy.py +141 -0
- llama_deploy/appserver/server.py +60 -0
- llama_deploy/appserver/settings.py +83 -0
- llama_deploy/appserver/source_managers/__init__.py +5 -0
- llama_deploy/appserver/source_managers/base.py +33 -0
- llama_deploy/appserver/source_managers/git.py +48 -0
- llama_deploy/appserver/source_managers/local.py +51 -0
- llama_deploy/appserver/stats.py +36 -0
- llama_deploy/appserver/tracing.py +237 -0
- llama_deploy/appserver/types.py +100 -0
- llama_deploy_appserver-0.2.7a1.dist-info/METADATA +23 -0
- llama_deploy_appserver-0.2.7a1.dist-info/RECORD +28 -0
- llama_deploy_appserver-0.2.7a1.dist-info/WHEEL +4 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
|
3
|
+
from pydantic import Field
|
4
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
5
|
+
|
6
|
+
|
7
|
+
class ApiserverSettings(BaseSettings):
|
8
|
+
model_config = SettingsConfigDict(env_prefix="LLAMA_DEPLOY_APISERVER_")
|
9
|
+
|
10
|
+
host: str = Field(
|
11
|
+
default="127.0.0.1",
|
12
|
+
description="The host where to run the API Server",
|
13
|
+
)
|
14
|
+
port: int = Field(
|
15
|
+
default=4501,
|
16
|
+
description="The TCP port where to bind the API Server",
|
17
|
+
)
|
18
|
+
rc_path: Path = Field(
|
19
|
+
default=Path("./.llama_deploy_rc"),
|
20
|
+
description="Path to the folder containing the deployment configs that will be loaded at startup",
|
21
|
+
)
|
22
|
+
deployments_path: Path | None = Field(
|
23
|
+
default=None,
|
24
|
+
description="Path to the folder where deployments will create their root path, defaults to a temp dir",
|
25
|
+
)
|
26
|
+
deployment_file_path: str | None = Field(
|
27
|
+
default=None,
|
28
|
+
description="Optional path, relative to the rc_path, where the deployment file is located. If not provided, will glob all .yml/.yaml files in the rc_path",
|
29
|
+
)
|
30
|
+
use_tls: bool = Field(
|
31
|
+
default=False,
|
32
|
+
description="Use TLS (HTTPS) to communicate with the API Server",
|
33
|
+
)
|
34
|
+
|
35
|
+
# Metrics collection settings
|
36
|
+
prometheus_enabled: bool = Field(
|
37
|
+
default=True,
|
38
|
+
description="Whether to enable the Prometheus metrics exporter along with the API Server",
|
39
|
+
)
|
40
|
+
prometheus_port: int = Field(
|
41
|
+
default=9000,
|
42
|
+
description="The port where to serve Prometheus metrics",
|
43
|
+
)
|
44
|
+
|
45
|
+
# Tracing settings
|
46
|
+
tracing_enabled: bool = Field(
|
47
|
+
default=False,
|
48
|
+
description="Enable OpenTelemetry tracing. Defaults to False.",
|
49
|
+
)
|
50
|
+
tracing_service_name: str = Field(
|
51
|
+
default="llama-deploy-appserver",
|
52
|
+
description="Service name for tracing. Defaults to 'llama-deploy-appserver'.",
|
53
|
+
)
|
54
|
+
tracing_exporter: str = Field(
|
55
|
+
default="console",
|
56
|
+
description="Trace exporter type: 'console', 'jaeger', 'otlp'. Defaults to 'console'.",
|
57
|
+
)
|
58
|
+
tracing_endpoint: str | None = Field(
|
59
|
+
default=None,
|
60
|
+
description="Trace exporter endpoint. Required for 'jaeger' and 'otlp' exporters.",
|
61
|
+
)
|
62
|
+
tracing_sample_rate: float = Field(
|
63
|
+
default=1.0,
|
64
|
+
description="Trace sampling rate (0.0 to 1.0). Defaults to 1.0 (100% sampling).",
|
65
|
+
)
|
66
|
+
tracing_insecure: bool = Field(
|
67
|
+
default=True,
|
68
|
+
description="Use insecure connection for OTLP exporter. Defaults to True.",
|
69
|
+
)
|
70
|
+
tracing_timeout: int = Field(
|
71
|
+
default=30,
|
72
|
+
description="Timeout in seconds for trace export. Defaults to 30.",
|
73
|
+
)
|
74
|
+
|
75
|
+
@property
|
76
|
+
def url(self) -> str:
|
77
|
+
protocol = "https://" if self.use_tls else "http://"
|
78
|
+
if self.port == 80:
|
79
|
+
return f"{protocol}{self.host}"
|
80
|
+
return f"{protocol}{self.host}:{self.port}"
|
81
|
+
|
82
|
+
|
83
|
+
settings = ApiserverSettings()
|
@@ -0,0 +1,33 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
from pathlib import Path
|
3
|
+
|
4
|
+
from llama_deploy.appserver.deployment_config_parser import DeploymentConfig, SyncPolicy
|
5
|
+
|
6
|
+
|
7
|
+
class SourceManager(ABC):
|
8
|
+
"""Protocol to be implemented by classes responsible for managing Deployment sources."""
|
9
|
+
|
10
|
+
def __init__(self, config: DeploymentConfig, base_path: Path | None = None) -> None:
|
11
|
+
self._config = config
|
12
|
+
self._base_path = base_path
|
13
|
+
|
14
|
+
@abstractmethod
|
15
|
+
def sync(
|
16
|
+
self,
|
17
|
+
source: str,
|
18
|
+
destination: str | None = None,
|
19
|
+
sync_policy: SyncPolicy = SyncPolicy.REPLACE,
|
20
|
+
) -> None: # pragma: no cover
|
21
|
+
"""Fetches resources from `source` so they can be used in a deployment.
|
22
|
+
|
23
|
+
Optionally uses `destination` to store data when this makes sense for the
|
24
|
+
specific source type.
|
25
|
+
"""
|
26
|
+
|
27
|
+
def relative_path(self, source: str) -> str:
|
28
|
+
"""Unfortunately, there's a difference in behavior of how the source managers sync.
|
29
|
+
The local source manager syncs the source into the <destination_path>/<source>, whereas
|
30
|
+
the git source manager just syncs the source into the <destination_path>. This is a temporary shim, since
|
31
|
+
changing this behavior is a breaking change to deployment.yaml configurations. Local source manager
|
32
|
+
overrides it. In a future major version, this behavior will be made consistent"""
|
33
|
+
return ""
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import shutil
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import Any
|
4
|
+
|
5
|
+
from git import Repo
|
6
|
+
|
7
|
+
from .base import SourceManager, SyncPolicy
|
8
|
+
|
9
|
+
|
10
|
+
class GitSourceManager(SourceManager):
|
11
|
+
"""A SourceManager specialized for sources of type `git`."""
|
12
|
+
|
13
|
+
def sync(
|
14
|
+
self,
|
15
|
+
source: str,
|
16
|
+
destination: str | None = None,
|
17
|
+
sync_policy: SyncPolicy = SyncPolicy.REPLACE,
|
18
|
+
) -> None:
|
19
|
+
"""Clones the repository at URL `source` into a local path `destination`.
|
20
|
+
|
21
|
+
Args:
|
22
|
+
source: The URL of the git repository. It can optionally contain a branch target using the name convention
|
23
|
+
`git_repo_url@branch_name`. For example, "https://example.com/llama_deploy.git@branch_name".
|
24
|
+
destination: The path in the local filesystem where to clone the git repository.
|
25
|
+
"""
|
26
|
+
if not destination:
|
27
|
+
raise ValueError("Destination cannot be empty")
|
28
|
+
|
29
|
+
if Path(destination).exists():
|
30
|
+
# FIXME: pull when SyncPolicy is MERGE
|
31
|
+
shutil.rmtree(destination)
|
32
|
+
|
33
|
+
url, branch_name = self._parse_source(source)
|
34
|
+
kwargs: dict[str, Any] = {"url": url, "to_path": destination}
|
35
|
+
if branch_name:
|
36
|
+
kwargs["multi_options"] = [f"-b {branch_name}", "--single-branch"]
|
37
|
+
|
38
|
+
Repo.clone_from(**kwargs) # type: ignore
|
39
|
+
|
40
|
+
@staticmethod
|
41
|
+
def _parse_source(source: str) -> tuple[str, str | None]:
|
42
|
+
branch_name = None
|
43
|
+
toks = source.split("@")
|
44
|
+
url = toks[0]
|
45
|
+
if len(toks) > 1:
|
46
|
+
branch_name = toks[1]
|
47
|
+
|
48
|
+
return url, branch_name
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import shutil
|
2
|
+
from pathlib import Path
|
3
|
+
|
4
|
+
from .base import SourceManager, SyncPolicy
|
5
|
+
|
6
|
+
|
7
|
+
class LocalSourceManager(SourceManager):
|
8
|
+
"""A SourceManager specialized for sources of type `local`."""
|
9
|
+
|
10
|
+
def sync(
|
11
|
+
self,
|
12
|
+
source: str,
|
13
|
+
destination: str | None = None,
|
14
|
+
sync_policy: SyncPolicy = SyncPolicy.REPLACE,
|
15
|
+
) -> None:
|
16
|
+
"""Copies the folder with path `source` into a local path `destination`.
|
17
|
+
|
18
|
+
Args:
|
19
|
+
source: The filesystem path to the folder containing the source code.
|
20
|
+
destination: The path in the local filesystem where to copy the source directory.
|
21
|
+
"""
|
22
|
+
if sync_policy == SyncPolicy.SKIP:
|
23
|
+
return
|
24
|
+
|
25
|
+
if not destination:
|
26
|
+
raise ValueError("Destination cannot be empty")
|
27
|
+
|
28
|
+
if Path(source).is_absolute():
|
29
|
+
raise ValueError("Source path must be relative to the deployment file")
|
30
|
+
|
31
|
+
base = self._base_path or Path()
|
32
|
+
final_path = base / source
|
33
|
+
destination_path = Path(destination)
|
34
|
+
dirs_exist_ok: bool = False
|
35
|
+
if destination_path.exists():
|
36
|
+
# Path is a non-empty directory
|
37
|
+
if sync_policy == SyncPolicy.REPLACE:
|
38
|
+
shutil.rmtree(destination_path)
|
39
|
+
elif sync_policy == SyncPolicy.MERGE:
|
40
|
+
dirs_exist_ok = True
|
41
|
+
|
42
|
+
try:
|
43
|
+
shutil.copytree(
|
44
|
+
final_path, destination_path / source, dirs_exist_ok=dirs_exist_ok
|
45
|
+
)
|
46
|
+
except Exception as e:
|
47
|
+
msg = f"Unable to copy {source} into {destination}: {e}"
|
48
|
+
raise ValueError(msg) from e
|
49
|
+
|
50
|
+
def relative_path(self, source: str) -> str:
|
51
|
+
return source
|
@@ -0,0 +1,36 @@
|
|
1
|
+
from prometheus_client import Enum
|
2
|
+
|
3
|
+
apiserver_state = Enum(
|
4
|
+
"apiserver_state",
|
5
|
+
"Current state of the API server",
|
6
|
+
states=[
|
7
|
+
"starting",
|
8
|
+
"running",
|
9
|
+
"stopped",
|
10
|
+
],
|
11
|
+
)
|
12
|
+
|
13
|
+
deployment_state = Enum(
|
14
|
+
"deployment_state",
|
15
|
+
"Current state of a deployment",
|
16
|
+
["deployment_name"],
|
17
|
+
states=[
|
18
|
+
"loading_services",
|
19
|
+
"ready",
|
20
|
+
"starting_services",
|
21
|
+
"running",
|
22
|
+
"stopped",
|
23
|
+
],
|
24
|
+
)
|
25
|
+
|
26
|
+
service_state = Enum(
|
27
|
+
"service_state",
|
28
|
+
"Current state of a service attached to a deployment",
|
29
|
+
["deployment_name", "service_name"],
|
30
|
+
states=[
|
31
|
+
"loading",
|
32
|
+
"syncing",
|
33
|
+
"installing",
|
34
|
+
"ready",
|
35
|
+
],
|
36
|
+
)
|
@@ -0,0 +1,237 @@
|
|
1
|
+
"""Tracing utilities for llama_deploy."""
|
2
|
+
|
3
|
+
import logging
|
4
|
+
from contextlib import contextmanager, nullcontext
|
5
|
+
from functools import wraps
|
6
|
+
from typing import TYPE_CHECKING, Any, Callable, Generator, TypeVar
|
7
|
+
|
8
|
+
if TYPE_CHECKING:
|
9
|
+
from llama_deploy.appserver.settings import ApiserverSettings
|
10
|
+
|
11
|
+
|
12
|
+
logger = logging.getLogger(__name__)
|
13
|
+
|
14
|
+
# Since opentelemetry is optional, we have to use Any to type the tracer
|
15
|
+
_tracer: Any | None = None
|
16
|
+
_tracing_enabled = False
|
17
|
+
_null_context = nullcontext()
|
18
|
+
|
19
|
+
F = TypeVar("F", bound=Callable[..., Any])
|
20
|
+
|
21
|
+
|
22
|
+
def configure_tracing(settings: "ApiserverSettings") -> None:
|
23
|
+
"""Configure OpenTelemetry tracing based on the provided configuration."""
|
24
|
+
global _tracer, _tracing_enabled
|
25
|
+
|
26
|
+
if not settings.tracing_enabled:
|
27
|
+
logger.debug("Tracing is disabled")
|
28
|
+
_tracing_enabled = False
|
29
|
+
return
|
30
|
+
|
31
|
+
try:
|
32
|
+
from opentelemetry import trace # type: ignore[import]
|
33
|
+
from opentelemetry.instrumentation.asyncio import AsyncioInstrumentor # type: ignore[import]
|
34
|
+
from opentelemetry.sdk.resources import SERVICE_NAME, Resource # type: ignore[import]
|
35
|
+
from opentelemetry.sdk.trace import TracerProvider # type: ignore[import]
|
36
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor # type: ignore[import]
|
37
|
+
from opentelemetry.sdk.trace.sampling import TraceIdRatioBased # type: ignore[import]
|
38
|
+
|
39
|
+
# Create resource with service name
|
40
|
+
resource = Resource.create({SERVICE_NAME: settings.tracing_service_name})
|
41
|
+
|
42
|
+
# Create tracer provider with sampling
|
43
|
+
tracer_provider = TracerProvider(
|
44
|
+
resource=resource, sampler=TraceIdRatioBased(settings.tracing_sample_rate)
|
45
|
+
)
|
46
|
+
|
47
|
+
# Configure exporter based on config
|
48
|
+
if settings.tracing_exporter == "console":
|
49
|
+
from opentelemetry.sdk.trace.export import ConsoleSpanExporter # type: ignore[import]
|
50
|
+
|
51
|
+
exporter = ConsoleSpanExporter()
|
52
|
+
|
53
|
+
elif settings.tracing_exporter == "otlp":
|
54
|
+
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import ( # type: ignore[import]
|
55
|
+
OTLPSpanExporter,
|
56
|
+
)
|
57
|
+
|
58
|
+
if not settings.tracing_endpoint:
|
59
|
+
raise ValueError("OTLP exporter requires an endpoint")
|
60
|
+
exporter = OTLPSpanExporter(
|
61
|
+
endpoint=f"{settings.tracing_endpoint}/v1/traces",
|
62
|
+
insecure=settings.tracing_insecure,
|
63
|
+
timeout=settings.tracing_timeout,
|
64
|
+
)
|
65
|
+
else:
|
66
|
+
raise ValueError(f"Unsupported exporter: {settings.tracing_exporter}")
|
67
|
+
|
68
|
+
# Add span processor
|
69
|
+
span_processor = BatchSpanProcessor(exporter)
|
70
|
+
tracer_provider.add_span_processor(span_processor)
|
71
|
+
|
72
|
+
# Set the global tracer provider
|
73
|
+
trace.set_tracer_provider(tracer_provider)
|
74
|
+
|
75
|
+
# Initialize global tracer
|
76
|
+
_tracer = trace.get_tracer(__name__)
|
77
|
+
_tracing_enabled = True
|
78
|
+
|
79
|
+
# Setup auto-instrumentation
|
80
|
+
AsyncioInstrumentor().instrument()
|
81
|
+
|
82
|
+
logger.info(
|
83
|
+
f"Tracing configured with {settings.tracing_exporter} exporter, service: {settings.tracing_service_name}"
|
84
|
+
)
|
85
|
+
|
86
|
+
except ImportError as e:
|
87
|
+
msg = (
|
88
|
+
f"Tracing is enabled but OpenTelemetry instrumentation packages are missing: {e}. "
|
89
|
+
"Run `pip install llama_deploy[observability]`"
|
90
|
+
)
|
91
|
+
logger.warning(msg)
|
92
|
+
_tracing_enabled = False
|
93
|
+
except Exception as e:
|
94
|
+
logger.error(f"Failed to configure tracing: {e}")
|
95
|
+
_tracing_enabled = False
|
96
|
+
|
97
|
+
|
98
|
+
def get_tracer() -> Any | None:
|
99
|
+
"""Get the configured tracer instance."""
|
100
|
+
return _tracer if _tracing_enabled else None
|
101
|
+
|
102
|
+
|
103
|
+
def is_tracing_enabled() -> bool:
|
104
|
+
"""Check if tracing is enabled."""
|
105
|
+
return _tracing_enabled
|
106
|
+
|
107
|
+
|
108
|
+
def trace_method(
|
109
|
+
span_name: str | None = None, attributes: dict | None = None
|
110
|
+
) -> Callable[[F], F]:
|
111
|
+
"""Decorator to add tracing to synchronous methods."""
|
112
|
+
|
113
|
+
def decorator(func: F) -> F:
|
114
|
+
if not _tracing_enabled:
|
115
|
+
return func
|
116
|
+
|
117
|
+
@wraps(func)
|
118
|
+
def wrapper(*args, **kwargs): # type: ignore
|
119
|
+
tracer = get_tracer()
|
120
|
+
if not tracer:
|
121
|
+
return func(*args, **kwargs)
|
122
|
+
|
123
|
+
name = span_name or f"{func.__module__}.{func.__qualname__}" # type: ignore
|
124
|
+
with tracer.start_as_current_span(name) as span:
|
125
|
+
if attributes:
|
126
|
+
span.set_attributes(attributes)
|
127
|
+
|
128
|
+
if hasattr(func, "__annotations__"):
|
129
|
+
for i, (param_name, _) in enumerate(func.__annotations__.items()):
|
130
|
+
if i < len(args) and param_name not in {"self", "cls"}:
|
131
|
+
span.set_attribute(
|
132
|
+
f"arg.{param_name}", str(args[i])[:100]
|
133
|
+
) # Truncate long values
|
134
|
+
|
135
|
+
try:
|
136
|
+
result = func(*args, **kwargs)
|
137
|
+
span.set_attribute("success", True)
|
138
|
+
return result
|
139
|
+
except Exception as e:
|
140
|
+
span.set_attribute("success", False)
|
141
|
+
span.set_attribute("error.type", type(e).__name__)
|
142
|
+
span.set_attribute("error.message", str(e))
|
143
|
+
raise
|
144
|
+
|
145
|
+
return wrapper # type: ignore
|
146
|
+
|
147
|
+
return decorator
|
148
|
+
|
149
|
+
|
150
|
+
def trace_async_method(
|
151
|
+
span_name: str | None = None, attributes: dict | None = None
|
152
|
+
) -> Callable[[F], F]:
|
153
|
+
"""Decorator to add tracing to asynchronous methods."""
|
154
|
+
|
155
|
+
def decorator(func: F) -> F:
|
156
|
+
if not _tracing_enabled:
|
157
|
+
return func
|
158
|
+
|
159
|
+
@wraps(func)
|
160
|
+
async def wrapper(*args, **kwargs): # type: ignore
|
161
|
+
tracer = get_tracer()
|
162
|
+
if not tracer:
|
163
|
+
return await func(*args, **kwargs)
|
164
|
+
|
165
|
+
name = span_name or f"{func.__module__}.{func.__qualname__}" # type: ignore
|
166
|
+
with tracer.start_as_current_span(name) as span:
|
167
|
+
if attributes:
|
168
|
+
span.set_attributes(attributes)
|
169
|
+
|
170
|
+
if hasattr(func, "__annotations__"):
|
171
|
+
for i, (param_name, _) in enumerate(func.__annotations__.items()):
|
172
|
+
if i < len(args) and param_name not in {"self", "cls"}:
|
173
|
+
span.set_attribute(
|
174
|
+
f"arg.{param_name}", str(args[i])[:100]
|
175
|
+
) # Truncate long values
|
176
|
+
|
177
|
+
try:
|
178
|
+
result = await func(*args, **kwargs)
|
179
|
+
span.set_attribute("success", True)
|
180
|
+
return result
|
181
|
+
except Exception as e:
|
182
|
+
span.set_attribute("success", False)
|
183
|
+
span.set_attribute("error.type", type(e).__name__)
|
184
|
+
span.set_attribute("error.message", str(e))
|
185
|
+
raise
|
186
|
+
|
187
|
+
return wrapper # type: ignore
|
188
|
+
|
189
|
+
return decorator
|
190
|
+
|
191
|
+
|
192
|
+
@contextmanager
|
193
|
+
def create_span(
|
194
|
+
name: str, attributes: dict | None = None
|
195
|
+
) -> Generator[Any, None, None]:
|
196
|
+
tracer = get_tracer()
|
197
|
+
if tracer is None:
|
198
|
+
yield
|
199
|
+
return
|
200
|
+
|
201
|
+
with tracer.start_as_current_span(name) as span:
|
202
|
+
if attributes:
|
203
|
+
for k, v in attributes.items():
|
204
|
+
span.set_attribute(k, v)
|
205
|
+
yield span
|
206
|
+
|
207
|
+
|
208
|
+
def add_span_attribute(key: str, value: Any) -> None:
|
209
|
+
"""Add an attribute to the current span if tracing is enabled."""
|
210
|
+
if not _tracing_enabled:
|
211
|
+
return
|
212
|
+
|
213
|
+
try:
|
214
|
+
from opentelemetry import trace # type: ignore[import]
|
215
|
+
|
216
|
+
current_span = trace.get_current_span()
|
217
|
+
if current_span:
|
218
|
+
current_span.set_attribute(key, str(value))
|
219
|
+
except Exception:
|
220
|
+
# Silently ignore tracing errors
|
221
|
+
pass
|
222
|
+
|
223
|
+
|
224
|
+
def add_span_event(name: str, attributes: dict | None = None) -> None:
|
225
|
+
"""Add an event to the current span if tracing is enabled."""
|
226
|
+
if not _tracing_enabled:
|
227
|
+
return
|
228
|
+
|
229
|
+
try:
|
230
|
+
from opentelemetry import trace # type: ignore[import]
|
231
|
+
|
232
|
+
current_span = trace.get_current_span()
|
233
|
+
if current_span:
|
234
|
+
current_span.add_event(name, attributes or {})
|
235
|
+
except Exception:
|
236
|
+
# Silently ignore tracing errors
|
237
|
+
pass
|
@@ -0,0 +1,100 @@
|
|
1
|
+
import uuid
|
2
|
+
from enum import Enum
|
3
|
+
|
4
|
+
from pydantic import BaseModel, Field
|
5
|
+
|
6
|
+
|
7
|
+
def generate_id() -> str:
|
8
|
+
return str(uuid.uuid4())
|
9
|
+
|
10
|
+
|
11
|
+
class TaskDefinition(BaseModel):
|
12
|
+
"""
|
13
|
+
The definition and state of a task.
|
14
|
+
|
15
|
+
Attributes:
|
16
|
+
input (str):
|
17
|
+
The task input.
|
18
|
+
session_id (str):
|
19
|
+
The session ID that the task belongs to.
|
20
|
+
task_id (str):
|
21
|
+
The task ID. Defaults to a random UUID.
|
22
|
+
service_id (str):
|
23
|
+
The service ID that the task should be sent to.
|
24
|
+
If blank, the orchestrator decides.
|
25
|
+
"""
|
26
|
+
|
27
|
+
input: str
|
28
|
+
task_id: str = Field(default_factory=generate_id)
|
29
|
+
session_id: str | None = None
|
30
|
+
service_id: str | None = None
|
31
|
+
|
32
|
+
|
33
|
+
class SessionDefinition(BaseModel):
|
34
|
+
"""
|
35
|
+
The definition of a session.
|
36
|
+
|
37
|
+
Attributes:
|
38
|
+
session_id (str):
|
39
|
+
The session ID. Defaults to a random UUID.
|
40
|
+
task_definitions (list[str]):
|
41
|
+
The task ids in order, representing the session.
|
42
|
+
state (dict):
|
43
|
+
The current session state.
|
44
|
+
"""
|
45
|
+
|
46
|
+
session_id: str = Field(default_factory=generate_id)
|
47
|
+
task_ids: list[str] = Field(default_factory=list)
|
48
|
+
state: dict = Field(default_factory=dict)
|
49
|
+
|
50
|
+
|
51
|
+
class EventDefinition(BaseModel):
|
52
|
+
"""The definition of event.
|
53
|
+
|
54
|
+
To be used as payloads for service endpoints when wanting to send serialized
|
55
|
+
Events.
|
56
|
+
|
57
|
+
Attributes:
|
58
|
+
event_object_str (str): serialized string of event.
|
59
|
+
"""
|
60
|
+
|
61
|
+
service_id: str
|
62
|
+
event_obj_str: str
|
63
|
+
|
64
|
+
|
65
|
+
class TaskResult(BaseModel):
|
66
|
+
"""
|
67
|
+
The result of a task.
|
68
|
+
|
69
|
+
Attributes:
|
70
|
+
task_id (str):
|
71
|
+
The task ID.
|
72
|
+
history (list[str]):
|
73
|
+
The task history.
|
74
|
+
result (str):
|
75
|
+
The task result.
|
76
|
+
data (dict):
|
77
|
+
Additional data about the task or result.
|
78
|
+
"""
|
79
|
+
|
80
|
+
task_id: str
|
81
|
+
history: list[str]
|
82
|
+
result: str
|
83
|
+
data: dict = Field(default_factory=dict)
|
84
|
+
|
85
|
+
|
86
|
+
class StatusEnum(Enum):
|
87
|
+
HEALTHY = "Healthy"
|
88
|
+
UNHEALTHY = "Unhealthy"
|
89
|
+
DOWN = "Down"
|
90
|
+
|
91
|
+
|
92
|
+
class Status(BaseModel):
|
93
|
+
status: StatusEnum
|
94
|
+
status_message: str
|
95
|
+
max_deployments: int | None = None
|
96
|
+
deployments: list[str] | None = None
|
97
|
+
|
98
|
+
|
99
|
+
class DeploymentDefinition(BaseModel):
|
100
|
+
name: str
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Metadata-Version: 2.3
|
2
|
+
Name: llama-deploy-appserver
|
3
|
+
Version: 0.2.7a1
|
4
|
+
Summary: Application server components for LlamaDeploy
|
5
|
+
Author: Massimiliano Pippi
|
6
|
+
Author-email: Massimiliano Pippi <mpippi@gmail.com>
|
7
|
+
License: MIT
|
8
|
+
Requires-Dist: asgiref>=3.9.1
|
9
|
+
Requires-Dist: llama-index-workflows>=1.1.0
|
10
|
+
Requires-Dist: pydantic-settings>=2.10.1
|
11
|
+
Requires-Dist: uvicorn>=0.24.0
|
12
|
+
Requires-Dist: prometheus-client>=0.20.0
|
13
|
+
Requires-Dist: python-multipart>=0.0.18,<0.0.19
|
14
|
+
Requires-Dist: fastapi>=0.100.0
|
15
|
+
Requires-Dist: websockets>=12.0
|
16
|
+
Requires-Dist: gitpython>=3.1.40,<4
|
17
|
+
Requires-Dist: llama-deploy-core>=0.2.7a1,<0.3.0
|
18
|
+
Requires-Dist: httpx>=0.28.1
|
19
|
+
Requires-Python: >=3.12, <4
|
20
|
+
Description-Content-Type: text/markdown
|
21
|
+
|
22
|
+
> [!WARNING]
|
23
|
+
> This repository contains pre-release software. It is unstable, incomplete, and subject to breaking changes. Not recommended for use.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
llama_deploy/appserver/__init__.py,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
|
2
|
+
llama_deploy/appserver/__main__.py,sha256=2dd2fe1f9ceff01038198515f30c107a82dc83ffd8c038d123f41893bf7fe4cb,333
|
3
|
+
llama_deploy/appserver/app.py,sha256=fbe5fa15e7dbb1ab4b98e29f838434023894b6adac8e099bc42ea9c4df990867,1506
|
4
|
+
llama_deploy/appserver/bootstrap.py,sha256=13b332df52ef763e20fe2ff9bcc20917508fee8153fae80569d942dc6be03793,1505
|
5
|
+
llama_deploy/appserver/client/__init__.py,sha256=1675fd1c7fb675700396e35fb9c83df093cc7ebb8ca01a4df4447d95991542f4,49
|
6
|
+
llama_deploy/appserver/client/base.py,sha256=2d6e5b263b55b393bc3ff383109d868e3c7a1e298388958476ec028c810004cf,1137
|
7
|
+
llama_deploy/appserver/client/client.py,sha256=7af5ab5359ed4cd8802749461f213b7b646984108023592eb15a04904dd96211,1312
|
8
|
+
llama_deploy/appserver/client/models/__init__.py,sha256=d1cb7f4948b34831f88951d51b2bd63699ae60bee07dbcfe8d20c4c77719e213,142
|
9
|
+
llama_deploy/appserver/client/models/apiserver.py,sha256=f258710196b55b5dd3d157a4d112d98947932314e6024019919749dced063a19,12511
|
10
|
+
llama_deploy/appserver/client/models/model.py,sha256=1f81dff71866610735f30efa978182f568e6fec5eff262a73ad526ecf3ffba6b,2655
|
11
|
+
llama_deploy/appserver/deployment.py,sha256=184dfe95476dd8eea8d3d63b9fed60ed37136f6f38ffa8d8fa66be107ded4e31,19207
|
12
|
+
llama_deploy/appserver/deployment_config_parser.py,sha256=4b4e2f20336c3b46db5ae64fccb663a8f1c4f970d24daebc8362809ab665ff80,4032
|
13
|
+
llama_deploy/appserver/routers/__init__.py,sha256=f882ea036d83f8239de66b6a17ae0a51865402e115310960680adff8ded49dab,129
|
14
|
+
llama_deploy/appserver/routers/deployments.py,sha256=7839423ea6c4621ddf5e18d91394cf0caecb0f099779b79f8f199dfd8f2e7583,14570
|
15
|
+
llama_deploy/appserver/routers/status.py,sha256=17b12f37ac92092fa5494b0ea3477f512972c05fc23c5fa56dc498e8e6120c75,1400
|
16
|
+
llama_deploy/appserver/run_autodeploy.py,sha256=36316cbe2df413d374dcef013f90ed5774a02a2012576356160e22397ae91bed,5000
|
17
|
+
llama_deploy/appserver/server.py,sha256=68b8db645e3b7323c140d12607812d9d21382aef5a5a1609d3cf30429440eddf,1991
|
18
|
+
llama_deploy/appserver/settings.py,sha256=1f0bbc8e69edd4007b6be3988b3576699470a1fb06fd3a38d977ef45be1e688b,2891
|
19
|
+
llama_deploy/appserver/source_managers/__init__.py,sha256=d52f325a4c84f16cfb220337afddcc6145dcfebc44564dc665d33442480e8f84,175
|
20
|
+
llama_deploy/appserver/source_managers/base.py,sha256=f8ef6f6b851b39d37e7f5ddd631656a8d0e1015470adfc59a53699e83b33e533,1400
|
21
|
+
llama_deploy/appserver/source_managers/git.py,sha256=ba197235f18297a29895f23a2534040337eddd0c2046fed88ac7f2d0a3038415,1577
|
22
|
+
llama_deploy/appserver/source_managers/local.py,sha256=9e80d5f2a2247779e15c6a7b19ceef75dec7e9b0877ac350530d0f5d81ac2d3f,1690
|
23
|
+
llama_deploy/appserver/stats.py,sha256=1f3989f6705a6de3e4d61ee8cdd189fbe04a2c53ec5e720b2e5168acc331427f,691
|
24
|
+
llama_deploy/appserver/tracing.py,sha256=211e0695041f2ebf3a05471035fdcff582263b8150df2a459b54932bed9a9194,8199
|
25
|
+
llama_deploy/appserver/types.py,sha256=f9e1e037f196d7a55af06095404ed33c8620d5c95f61c8bc87df75b6e714897f,2237
|
26
|
+
llama_deploy_appserver-0.2.7a1.dist-info/WHEEL,sha256=cc8ae5806c5874a696cde0fcf78fdf73db4982e7c824f3ceab35e2b65182fa1a,79
|
27
|
+
llama_deploy_appserver-0.2.7a1.dist-info/METADATA,sha256=7b2c8925c464b72bf518926eb786afff346ff5bb1dad7caf254802ecf8350dd2,845
|
28
|
+
llama_deploy_appserver-0.2.7a1.dist-info/RECORD,,
|