Skip to content

Commit 0298748

Browse files
authored
Supoprt agent.create and agent.execute (#113)
1 parent 7983536 commit 0298748

File tree

5 files changed

+413
-83
lines changed

5 files changed

+413
-83
lines changed

tests/conftest.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ def __init__(self, api_key=None, base_url=None):
9898
self.document = self.DocumentPredictions(self)
9999
self.audio = self.AudioPredictions(self)
100100
self.feedback = self.Feedback(self)
101+
self.agent = self.Agent(self)
101102

102103
class FineTuning:
103104
def __init__(self, client):
@@ -469,6 +470,126 @@ def get(self, request_id, limit=10, offset=0):
469470
],
470471
)
471472

473+
class Agent:
474+
def __init__(self, client):
475+
self._client = client
476+
477+
def get(self, name=None, version=None, id=None):
478+
from vlmrun.client.types import AgentInfo
479+
from datetime import datetime
480+
481+
if id and name:
482+
raise ValueError("Only one of `id` or `name` can be provided.")
483+
if not id and not name:
484+
raise ValueError("Either `id` or `name` must be provided.")
485+
486+
if id:
487+
agent_id = id
488+
agent_name = f"agent-{id}"
489+
else:
490+
agent_id = f"agent-{name}-{version or 'latest'}"
491+
agent_name = name
492+
493+
return AgentInfo(
494+
id=agent_id,
495+
name=agent_name,
496+
version=version or "latest",
497+
description="Test agent description",
498+
prompt="Test agent prompt",
499+
json_schema={
500+
"type": "object",
501+
"properties": {"result": {"type": "string"}},
502+
},
503+
json_sample={"result": "test result"},
504+
created_at=datetime.fromisoformat("2024-01-01T00:00:00+00:00"),
505+
updated_at=datetime.fromisoformat("2024-01-01T00:00:00+00:00"),
506+
status="completed",
507+
)
508+
509+
def list(self):
510+
from vlmrun.client.types import AgentInfo
511+
from datetime import datetime
512+
513+
return [
514+
AgentInfo(
515+
id="agent-1",
516+
name="test-agent-1",
517+
version="1.0.0",
518+
description="First test agent",
519+
prompt="Test prompt 1",
520+
json_schema={
521+
"type": "object",
522+
"properties": {"result": {"type": "string"}},
523+
},
524+
json_sample={"result": "test result 1"},
525+
created_at=datetime.fromisoformat("2024-01-01T00:00:00+00:00"),
526+
updated_at=datetime.fromisoformat("2024-01-01T00:00:00+00:00"),
527+
status="completed",
528+
),
529+
AgentInfo(
530+
id="agent-2",
531+
name="test-agent-2",
532+
version="2.0.0",
533+
description="Second test agent",
534+
prompt="Test prompt 2",
535+
json_schema={
536+
"type": "object",
537+
"properties": {"output": {"type": "string"}},
538+
},
539+
json_sample={"output": "test output 2"},
540+
created_at=datetime.fromisoformat("2024-01-02T00:00:00+00:00"),
541+
updated_at=datetime.fromisoformat("2024-01-02T00:00:00+00:00"),
542+
status="completed",
543+
),
544+
]
545+
546+
def create(self, config, name=None, inputs=None, callback_url=None):
547+
from vlmrun.client.types import AgentCreationResponse
548+
from datetime import datetime
549+
550+
if config.prompt is None:
551+
raise ValueError(
552+
"Prompt is not provided as a request parameter, please provide a prompt."
553+
)
554+
555+
return AgentCreationResponse(
556+
id=f"agent-{name or 'created'}",
557+
name=name or "created-agent",
558+
version="1.0.0",
559+
created_at=datetime.fromisoformat("2024-01-01T00:00:00+00:00"),
560+
updated_at=datetime.fromisoformat("2024-01-01T00:00:00+00:00"),
561+
status="pending",
562+
)
563+
564+
def execute(
565+
self,
566+
name,
567+
version=None,
568+
inputs=None,
569+
batch=True,
570+
config=None,
571+
metadata=None,
572+
callback_url=None,
573+
):
574+
from vlmrun.client.types import AgentExecutionResponse, CreditUsage
575+
from datetime import datetime
576+
577+
if not batch:
578+
raise NotImplementedError(
579+
"Batch mode is required for agent execution"
580+
)
581+
582+
return AgentExecutionResponse(
583+
id=f"execution-{name}",
584+
name=name,
585+
version=version or "latest",
586+
status="completed",
587+
created_at=datetime.fromisoformat("2024-01-01T00:00:00+00:00"),
588+
completed_at=datetime.fromisoformat("2024-01-01T00:00:01+00:00"),
589+
response={"result": "execution result"},
590+
usage=CreditUsage(credits_used=50),
591+
)
592+
472593
monkeypatch.setattr("vlmrun.cli.cli.VLMRun", MockVLMRun)
473594
return MockVLMRun()
474595

tests/test_agent.py

Lines changed: 173 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
"""Tests for the Agent resource."""
22

3+
import pytest
34
from datetime import datetime
4-
from vlmrun.client.types import AgentCreationResponse
5+
from vlmrun.client.types import (
6+
AgentCreationResponse,
7+
AgentCreationConfig,
8+
AgentExecutionConfig,
9+
AgentExecutionResponse,
10+
AgentInfo,
11+
CreditUsage,
12+
)
513

614

715
class TestAgentCreationResponse:
@@ -13,74 +21,183 @@ def test_agent_creation_response_creation(self):
1321
"id": "test-agent-123",
1422
"name": "Test Agent",
1523
"version": "1.0.0",
16-
"description": "A test agent for testing purposes",
1724
"created_at": datetime.now(),
1825
"updated_at": datetime.now(),
19-
"output_json_schema": {
20-
"type": "object",
21-
"properties": {"result": {"type": "string"}},
22-
},
23-
"output_json_sample": {"result": "test result"},
24-
"input_type": "document",
25-
"input_json_schema": None,
26+
"status": "completed",
2627
}
2728

2829
response = AgentCreationResponse(**response_data)
2930

3031
assert response.id == "test-agent-123"
3132
assert response.name == "Test Agent"
3233
assert response.version == "1.0.0"
33-
assert response.description == "A test agent for testing purposes"
34-
assert response.input_type == "document"
35-
assert response.input_json_schema is None
36-
assert "result" in response.output_json_schema["properties"]
37-
assert response.output_json_sample["result"] == "test result"
38-
39-
def test_agent_creation_response_with_input_schema(self):
40-
"""Test creating an AgentCreationResponse with input schema."""
41-
response_data = {
42-
"id": "test-agent-456",
43-
"name": "Test Agent with Input Schema",
44-
"version": "2.0.0",
45-
"description": "A test agent with input schema",
46-
"created_at": datetime.now(),
47-
"updated_at": datetime.now(),
48-
"output_json_schema": {
34+
assert response.status == "completed"
35+
36+
37+
class TestAgentMethods:
38+
"""Test the Agent API methods."""
39+
40+
def test_agent_get_by_name_and_version(self, mock_client):
41+
"""Test getting an agent by name and version."""
42+
client = mock_client
43+
response = client.agent.get(name="test-agent", version="1.0.0")
44+
45+
assert isinstance(response, AgentInfo)
46+
assert response.name == "test-agent"
47+
assert response.version == "1.0.0"
48+
assert response.description == "Test agent description"
49+
assert response.prompt == "Test agent prompt"
50+
assert response.status == "completed"
51+
52+
def test_agent_get_by_id(self, mock_client):
53+
"""Test getting an agent by ID."""
54+
client = mock_client
55+
response = client.agent.get(id="agent-123")
56+
57+
assert isinstance(response, AgentInfo)
58+
assert response.id == "agent-123"
59+
assert response.name == "agent-agent-123"
60+
assert response.version == "latest"
61+
62+
def test_agent_get_validation_error(self, mock_client):
63+
"""Test that get method validates input parameters."""
64+
client = mock_client
65+
66+
with pytest.raises(
67+
ValueError, match="Only one of `id` or `name` can be provided."
68+
):
69+
client.agent.get(id="agent-123", name="test-agent")
70+
71+
with pytest.raises(ValueError, match="Either `id` or `name` must be provided."):
72+
client.agent.get()
73+
74+
def test_agent_list(self, mock_client):
75+
"""Test listing all agents."""
76+
client = mock_client
77+
response = client.agent.list()
78+
79+
assert isinstance(response, list)
80+
assert len(response) == 2
81+
assert all(isinstance(agent, AgentInfo) for agent in response)
82+
assert response[0].name == "test-agent-1"
83+
assert response[1].name == "test-agent-2"
84+
85+
def test_agent_create(self, mock_client):
86+
"""Test creating an agent."""
87+
client = mock_client
88+
config = AgentCreationConfig(
89+
prompt="Create a test agent",
90+
json_schema={
91+
"type": "object",
92+
"properties": {"result": {"type": "string"}},
93+
},
94+
)
95+
96+
response = client.agent.create(
97+
config=config, name="new-agent", inputs={"test": "input"}
98+
)
99+
100+
assert isinstance(response, AgentCreationResponse)
101+
assert response.name == "new-agent"
102+
assert response.version == "1.0.0"
103+
assert response.status == "pending"
104+
105+
def test_agent_create_validation_error(self, mock_client):
106+
"""Test that create method validates config has prompt."""
107+
client = mock_client
108+
config = AgentCreationConfig()
109+
110+
with pytest.raises(
111+
ValueError,
112+
match="Prompt is not provided as a request parameter, please provide a prompt.",
113+
):
114+
client.agent.create(config=config)
115+
116+
def test_agent_execute(self, mock_client):
117+
"""Test executing an agent."""
118+
client = mock_client
119+
config = AgentExecutionConfig(
120+
prompt="Execute this agent",
121+
json_schema={
49122
"type": "object",
50123
"properties": {"output": {"type": "string"}},
51124
},
52-
"output_json_sample": {"output": "test output"},
53-
"input_type": "mixed",
54-
"input_json_schema": {
125+
)
126+
127+
response = client.agent.execute(
128+
name="test-agent",
129+
version="1.0.0",
130+
inputs={"input": "test data"},
131+
config=config,
132+
)
133+
134+
assert isinstance(response, AgentExecutionResponse)
135+
assert response.name == "test-agent"
136+
assert response.version == "1.0.0"
137+
assert response.status == "completed"
138+
assert response.response == {"result": "execution result"}
139+
assert isinstance(response.usage, CreditUsage)
140+
assert response.usage.credits_used == 50
141+
142+
def test_agent_execute_without_version(self, mock_client):
143+
"""Test executing an agent without specifying version."""
144+
client = mock_client
145+
146+
response = client.agent.execute(name="test-agent")
147+
148+
assert isinstance(response, AgentExecutionResponse)
149+
assert response.name == "test-agent"
150+
assert response.version == "latest"
151+
152+
def test_agent_execute_batch_mode_required(self, mock_client):
153+
"""Test that execute method requires batch mode."""
154+
client = mock_client
155+
156+
with pytest.raises(
157+
NotImplementedError, match="Batch mode is required for agent execution"
158+
):
159+
client.agent.execute(name="test-agent", batch=False)
160+
161+
162+
class TestAgentConfigModels:
163+
"""Test the Agent configuration models."""
164+
165+
def test_agent_creation_config(self):
166+
"""Test AgentCreationConfig model."""
167+
config = AgentCreationConfig(
168+
prompt="Test prompt",
169+
json_schema={
170+
"type": "object",
171+
"properties": {"result": {"type": "string"}},
172+
},
173+
)
174+
175+
assert config.prompt == "Test prompt"
176+
assert config.json_schema is not None
177+
assert config.response_model is None
178+
179+
def test_agent_execution_config(self):
180+
"""Test AgentExecutionConfig model."""
181+
config = AgentExecutionConfig(
182+
prompt="Execute prompt",
183+
json_schema={
55184
"type": "object",
56-
"properties": {"input": {"type": "string"}},
185+
"properties": {"output": {"type": "string"}},
57186
},
58-
}
187+
)
59188

60-
response = AgentCreationResponse(**response_data)
189+
assert config.prompt == "Execute prompt"
190+
assert config.json_schema is not None
191+
assert config.response_model is None
192+
193+
def test_config_validation_error(self):
194+
"""Test that config validates response_model and json_schema are not both provided."""
195+
from pydantic import BaseModel
196+
197+
class TestModel(BaseModel):
198+
result: str
61199

62-
assert response.id == "test-agent-456"
63-
assert response.input_type == "mixed"
64-
assert response.input_json_schema is not None
65-
assert "input" in response.input_json_schema["properties"]
66-
67-
def test_agent_creation_response_input_types(self):
68-
"""Test that all input types are accepted."""
69-
valid_input_types = ["text", "document", "image", "video", "audio", "mixed"]
70-
71-
for input_type in valid_input_types:
72-
response_data = {
73-
"id": f"test-agent-{input_type}",
74-
"name": f"Test Agent {input_type}",
75-
"version": "1.0.0",
76-
"description": f"A test agent for {input_type}",
77-
"created_at": datetime.now(),
78-
"updated_at": datetime.now(),
79-
"output_json_schema": {"type": "object", "properties": {}},
80-
"output_json_sample": {},
81-
"input_type": input_type,
82-
"input_json_schema": None,
83-
}
84-
85-
response = AgentCreationResponse(**response_data)
86-
assert response.input_type == input_type
200+
with pytest.raises(ValueError, match="cannot be used together"):
201+
AgentCreationConfig(
202+
prompt="Test", response_model=TestModel, json_schema={"type": "object"}
203+
)

0 commit comments

Comments
 (0)