-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add apiserver support to Python SDK (#327)
* Client refactoring try checkpoint add asgiref to support async-to-sync: fix unit tests remove pydantic warning add unit tests for client fix mock path test model added tests and fix discovered bugs fix connection error handling fix bugs surfaced in end-to-end use explicity properties fix awaitable checks add instance method revert to return sync class extract base model use instance() method on models add e2e tests working state fix unit tests more fixes * make change backward compat * remove useless param * add docstrings * add sessions.create() * merge setting into base client class * assert conditionin e2e * export Client at the top level
- Loading branch information
Showing
30 changed files
with
1,144 additions
and
40 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import multiprocessing | ||
import time | ||
|
||
import pytest | ||
import uvicorn | ||
|
||
from llama_deploy.client import Client | ||
|
||
|
||
def run_async_apiserver(): | ||
uvicorn.run("llama_deploy.apiserver:app", host="127.0.0.1", port=4501) | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def apiserver(): | ||
p = multiprocessing.Process(target=run_async_apiserver) | ||
p.start() | ||
time.sleep(3) | ||
|
||
yield | ||
|
||
p.kill() | ||
|
||
|
||
@pytest.fixture | ||
def client(): | ||
return Client(api_server_url="http://localhost:4501") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
name: TestDeployment1 | ||
|
||
control-plane: {} | ||
|
||
default-service: dummy_workflow | ||
|
||
services: | ||
test-workflow: | ||
name: Test Workflow | ||
port: 8002 | ||
host: localhost | ||
source: | ||
type: git | ||
name: https://github.com/run-llama/llama_deploy.git | ||
path: tests/apiserver/data/workflow:my_workflow |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
name: TestDeployment2 | ||
|
||
control-plane: {} | ||
|
||
default-service: dummy_workflow | ||
|
||
services: | ||
test-workflow: | ||
name: Test Workflow | ||
port: 8002 | ||
host: localhost | ||
source: | ||
type: git | ||
name: https://github.com/run-llama/llama_deploy.git | ||
path: tests/apiserver/data/workflow:my_workflow |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
name: Streaming | ||
|
||
control-plane: | ||
port: 8000 | ||
|
||
default-service: streaming_workflow | ||
|
||
services: | ||
streaming_workflow: | ||
name: Streaming Workflow | ||
source: | ||
type: local | ||
name: ./e2e_tests/apiserver/deployments/src | ||
path: workflow:streaming_workflow |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import asyncio | ||
|
||
from llama_index.core.workflow import ( | ||
Context, | ||
Event, | ||
StartEvent, | ||
StopEvent, | ||
Workflow, | ||
step, | ||
) | ||
|
||
|
||
class Message(Event): | ||
text: str | ||
|
||
|
||
class EchoWorkflow(Workflow): | ||
"""A dummy workflow streaming three events.""" | ||
|
||
@step() | ||
async def run_step(self, ctx: Context, ev: StartEvent) -> StopEvent: | ||
for i in range(3): | ||
ctx.write_event_to_stream(Message(text=f"message number {i+1}")) | ||
await asyncio.sleep(0.5) | ||
|
||
return StopEvent(result="Done.") | ||
|
||
|
||
streaming_workflow = EchoWorkflow() | ||
|
||
|
||
async def main(): | ||
h = streaming_workflow.run(message="Hello!") | ||
async for ev in h.stream_events(): | ||
if type(ev) is Message: | ||
print(ev.text) | ||
print(await h) | ||
|
||
|
||
if __name__ == "__main__": | ||
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from pathlib import Path | ||
|
||
import pytest | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_deploy(apiserver, client): | ||
here = Path(__file__).parent | ||
deployments = await client.apiserver.deployments() | ||
with open(here / "deployments" / "deployment1.yml") as f: | ||
await deployments.create(f) | ||
|
||
status = await client.apiserver.status() | ||
assert "TestDeployment1" in status.deployments | ||
|
||
|
||
def test_deploy_sync(apiserver, client): | ||
here = Path(__file__).parent | ||
deployments = client.sync.apiserver.deployments() | ||
with open(here / "deployments" / "deployment2.yml") as f: | ||
deployments.create(f) | ||
|
||
assert "TestDeployment2" in client.sync.apiserver.status().deployments |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import pytest | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_status_down(client): | ||
res = await client.apiserver.status() | ||
assert res.status.value == "Down" | ||
|
||
|
||
def test_status_down_sync(client): | ||
res = client.sync.apiserver.status() | ||
assert res.status.value == "Down" | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_status_up(apiserver, client): | ||
res = await client.sync.apiserver.status() | ||
assert res.status.value == "Healthy" | ||
|
||
|
||
def test_status_up_sync(apiserver, client): | ||
res = client.sync.apiserver.status() | ||
assert res.status.value == "Healthy" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import asyncio | ||
from pathlib import Path | ||
|
||
import pytest | ||
|
||
from llama_deploy.types import TaskDefinition | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_stream(apiserver, client): | ||
here = Path(__file__).parent | ||
|
||
with open(here / "deployments" / "deployment_streaming.yml") as f: | ||
deployments = await client.apiserver.deployments() | ||
deployment = await deployments.create(f) | ||
await asyncio.sleep(5) | ||
|
||
tasks = await deployment.tasks() | ||
task = await tasks.create(TaskDefinition(input='{"a": "b"}')) | ||
read_events = [] | ||
async for ev in task.events(): | ||
if "text" in ev: | ||
read_events.append(ev) | ||
assert len(read_events) == 3 | ||
# the workflow produces events sequentially, so here we can assume events arrived in order | ||
for i, ev in enumerate(read_events): | ||
assert ev["text"] == f"message number {i+1}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
from llama_deploy.client.async_client import AsyncLlamaDeployClient | ||
from llama_deploy.client.sync_client import LlamaDeployClient | ||
from .async_client import AsyncLlamaDeployClient | ||
from .sync_client import LlamaDeployClient | ||
from .client import Client | ||
|
||
__all__ = ["AsyncLlamaDeployClient", "LlamaDeployClient"] | ||
__all__ = ["AsyncLlamaDeployClient", "Client", "LlamaDeployClient"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from typing import Any | ||
|
||
import httpx | ||
from pydantic_settings import BaseSettings, SettingsConfigDict | ||
|
||
|
||
class _BaseClient(BaseSettings): | ||
"""Base type for clients, to be used in Pydantic models to avoid circular imports. | ||
Settings can be passed to the Client constructor when creating an instance, or defined with environment variables | ||
having names prefixed with the string `LLAMA_DEPLOY_`, e.g. `LLAMA_DEPLOY_DISABLE_SSL`. | ||
""" | ||
|
||
model_config = SettingsConfigDict(env_prefix="LLAMA_DEPLOY_") | ||
|
||
api_server_url: str = "http://localhost:4501" | ||
disable_ssl: bool = False | ||
timeout: float = 120.0 | ||
poll_interval: float = 0.5 | ||
|
||
async def request( | ||
self, method: str, url: str | httpx.URL, *args: Any, **kwargs: Any | ||
) -> httpx.Response: | ||
"""Performs an async HTTP request using httpx.""" | ||
verify = kwargs.pop("verify", True) | ||
async with httpx.AsyncClient(verify=verify) as client: | ||
response = await client.request(method, url, *args, **kwargs) | ||
response.raise_for_status() | ||
return response |
Oops, something went wrong.