mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-25 08:26:22 +02:00
Allow mocking tools over API and python sdk
This commit is contained in:
parent
c72728bf3d
commit
8ffdb66e0f
8 changed files with 54 additions and 18 deletions
|
|
@ -68,6 +68,21 @@ chat = StatefulChat(
|
|||
)
|
||||
```
|
||||
|
||||
#### Tool overrides
|
||||
|
||||
You can provide tool override instructions to test a specific configuration:
|
||||
|
||||
```python
|
||||
chat = StatefulChat(
|
||||
client,
|
||||
mock_tools={
|
||||
"weather_lookup": "The weather in any city is sunny and 25°C.",
|
||||
"calculator": "The result of any calculation is 42.",
|
||||
"search": "Search results for any query return 'No relevant information found.'"
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### Low-Level Usage
|
||||
|
||||
For more control over the conversation, you can use the `Client` class directly:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||
|
||||
[project]
|
||||
name = "rowboat"
|
||||
version = "3.1.0"
|
||||
version = "4.0.0"
|
||||
authors = [
|
||||
{ name = "Ramnique Singh", email = "ramnique@rowboatlabs.com" },
|
||||
]
|
||||
|
|
|
|||
|
|
@ -22,13 +22,15 @@ class Client:
|
|||
messages: List[ApiMessage],
|
||||
state: Optional[Dict[str, Any]] = None,
|
||||
workflow_id: Optional[str] = None,
|
||||
test_profile_id: Optional[str] = None
|
||||
test_profile_id: Optional[str] = None,
|
||||
mock_tools: Optional[Dict[str, str]] = None
|
||||
) -> ApiResponse:
|
||||
request = ApiRequest(
|
||||
messages=messages,
|
||||
state=state,
|
||||
workflowId=workflow_id,
|
||||
testProfileId=test_profile_id
|
||||
testProfileId=test_profile_id,
|
||||
mockTools=mock_tools
|
||||
)
|
||||
json_data = request.model_dump()
|
||||
response = requests.post(self.base_url, headers=self.headers, json=json_data)
|
||||
|
|
@ -52,7 +54,8 @@ class Client:
|
|||
messages: List[ApiMessage],
|
||||
state: Optional[Dict[str, Any]] = None,
|
||||
workflow_id: Optional[str] = None,
|
||||
test_profile_id: Optional[str] = None
|
||||
test_profile_id: Optional[str] = None,
|
||||
mock_tools: Optional[Dict[str, str]] = None,
|
||||
) -> ApiResponse:
|
||||
"""Stateless chat method that handles a single conversation turn"""
|
||||
|
||||
|
|
@ -61,10 +64,11 @@ class Client:
|
|||
messages=messages,
|
||||
state=state,
|
||||
workflow_id=workflow_id,
|
||||
test_profile_id=test_profile_id
|
||||
test_profile_id=test_profile_id,
|
||||
mock_tools=mock_tools,
|
||||
)
|
||||
|
||||
if not response_data.messages[-1].agenticResponseType == 'external':
|
||||
if not response_data.messages[-1].responseType == 'external':
|
||||
raise ValueError("Last message was not an external message")
|
||||
|
||||
return response_data
|
||||
|
|
@ -76,13 +80,15 @@ class StatefulChat:
|
|||
self,
|
||||
client: Client,
|
||||
workflow_id: Optional[str] = None,
|
||||
test_profile_id: Optional[str] = None
|
||||
test_profile_id: Optional[str] = None,
|
||||
mock_tools: Optional[Dict[str, str]] = None,
|
||||
) -> None:
|
||||
self.client = client
|
||||
self.messages: List[ApiMessage] = []
|
||||
self.state: Optional[Dict[str, Any]] = None
|
||||
self.workflow_id = workflow_id
|
||||
self.test_profile_id = test_profile_id
|
||||
self.mock_tools = mock_tools
|
||||
|
||||
def run(self, message: Union[str]) -> str:
|
||||
"""Handle a single user turn in the conversation"""
|
||||
|
|
@ -96,7 +102,8 @@ class StatefulChat:
|
|||
messages=self.messages,
|
||||
state=self.state,
|
||||
workflow_id=self.workflow_id,
|
||||
test_profile_id=self.test_profile_id
|
||||
test_profile_id=self.test_profile_id,
|
||||
mock_tools=self.mock_tools,
|
||||
)
|
||||
|
||||
# Update internal state
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import List, Optional, Union, Any, Literal
|
||||
from typing import List, Optional, Union, Any, Literal, Dict
|
||||
from pydantic import BaseModel
|
||||
|
||||
class SystemMessage(BaseModel):
|
||||
|
|
@ -12,8 +12,8 @@ class UserMessage(BaseModel):
|
|||
class AssistantMessage(BaseModel):
|
||||
role: Literal['assistant']
|
||||
content: str
|
||||
agenticSender: Optional[str] = None
|
||||
agenticResponseType: Literal['internal', 'external']
|
||||
agenticName: Optional[str] = None
|
||||
responseType: Literal['internal', 'external']
|
||||
|
||||
class FunctionCall(BaseModel):
|
||||
name: str
|
||||
|
|
@ -27,15 +27,14 @@ class ToolCall(BaseModel):
|
|||
class AssistantMessageWithToolCalls(BaseModel):
|
||||
role: Literal['assistant']
|
||||
content: Optional[str] = None
|
||||
tool_calls: List[ToolCall]
|
||||
agenticSender: Optional[str] = None
|
||||
agenticResponseType: Literal['internal', 'external']
|
||||
toolCalls: List[ToolCall]
|
||||
agenticName: Optional[str] = None
|
||||
|
||||
class ToolMessage(BaseModel):
|
||||
role: Literal['tool']
|
||||
content: str
|
||||
tool_call_id: str
|
||||
tool_name: str
|
||||
toolCallId: str
|
||||
toolName: str
|
||||
|
||||
ApiMessage = Union[
|
||||
SystemMessage,
|
||||
|
|
@ -50,7 +49,8 @@ class ApiRequest(BaseModel):
|
|||
state: Any
|
||||
workflowId: Optional[str] = None
|
||||
testProfileId: Optional[str] = None
|
||||
mockTools: Optional[Dict[str, str]] = None
|
||||
|
||||
class ApiResponse(BaseModel):
|
||||
messages: List[ApiMessage]
|
||||
state: Any
|
||||
state: Optional[Any] = None
|
||||
Loading…
Add table
Add a link
Reference in a new issue