Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: API endpoints for sotopia #242

Merged
merged 21 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ groq = ["groq"]
cohere = ["cohere"]
google-generativeai = ["google-generativeai"]
examples = ["transformers", "datasets", "scipy", "torch", "pandas"]
chat = ["fastapi"]
chat = [
"fastapi[standard]",
"uvicorn",
]
test = ["pytest", "pytest-cov", "pytest-asyncio"]

[tool.uv]
Expand Down
194 changes: 194 additions & 0 deletions sotopia/ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Sotopia UI
XuhuiZhou marked this conversation as resolved.
Show resolved Hide resolved
> [!CAUTION]
> Work in progress: the API endpoints are being implemented. And will be released in the future major version.

## FastAPI Server

The API server is a FastAPI application that is used to connect the Sotopia UI to the Sotopia backend.
This could also help with other projects that need to connect to the Sotopia backend through HTTP requests.

Here are some initial design of the API server:

### Getting Data from the API Server

#### GET /scenarios

Get all scenarios.

returns:
- scenarios: list[EnvironmentProfile]

#### GET /scenarios/?get_by={id|tag}/{scenario_id|scenario_tag}

Get scenarios by scenario_tag.
parameters:
- get_by: Literal["id", "tag"]
- scenario_id: str or scenario_tag: str
(This scenario tag could be a keyword; so people can search for scenarios by keywords)

returns:
- scenarios: list[EnvironmentProfile]

#### GET /agents

Get all agents.

returns:
- agents: list[AgentProfile]

#### GET /agents/?get_by={id|gender|occupation}/{value}

Get agents by id, gender, or occupation.
parameters:
- get_by: Literal["id", "gender", "occupation"]
- value: str (agent_id, agent_gender, or agent_occupation)

returns:
- agents: list[AgentProfile]


#### GET /episodes

Get all episodes.

returns:
- episodes: list[Episode]

#### GET /episodes/?get_by={id|tag}/{episode_id|episode_tag}

Get episode by episode_tag.
XuhuiZhou marked this conversation as resolved.
Show resolved Hide resolved
parameters:
- get_by: Literal["id", "tag"]
- episode_id: str or episode_tag: str

returns:
- episodes: list[Episode]


### Sending Data to the API Server

#### POST /agents/

Send agent profile to the API server.
Request Body:
AgentProfile

returns:
- agent_id: str

#### POST /scenarios/

Send scenario profile to the API server.
Request Body:
EnvironmentProfile

returns:
- scenario_id: str

### Updating Data in the API Server

#### PUT /agents/{agent_id}

Update agent profile in the API server.
Request Body:
AgentProfile

returns:
- agent_id: str


#### PUT /scenarios/{scenario_id}

Update scenario profile in the API server.
Request Body:
EnvironmentProfile

returns:
- scenario_id: str


### Error Code
For RESTful APIs above we have the following error codes:
| **Error Code** | **Description** |
|-----------------|--------------------------------------|
| **404** | A resource is not found |
| **403** | The query is not authorized |
| **500** | Internal running error |

### Initiating a new non-streaming simulation episode

#### POST /episodes/
[!] Currently not planning to implement
```python
class SimulationEpisodeInitiation(BaseModel):
scenario_id: str
agent_ids: list[str]
episode_tag: str
models: list[str]
```

Send episode profile to the API server.
Request Body:
SimulationEpisodeInitiation

returns:
- episode_id: str (This is the id of the episode that will be used to get the episode data, saved in the redis database)

### Initiating a new interactive streaming simulation episode (this operation will open a websocket connection)

We use the websocket connection to send the simulation step-by-step results to the UI.
ProKil marked this conversation as resolved.
Show resolved Hide resolved
Please see an example protocol [here](https://claude.site/artifacts/322011f6-597f-4819-8afb-bf8137dfb56a)
ProKil marked this conversation as resolved.
Show resolved Hide resolved

#### WEBSOCKET /ws/simulate/?token={token}

Parameters:
- Token: String. User authentication token. Each token maps to a unique session.

returns:
- msg: WSMessage

**WSMessage**
```json
{
"type": "WSMessageType",
"data": {
// Message-specific payload
}
}
```

**WSMessageType**
| Type | Direction | Description |
|-----------|--------|-------------|
| SERVER_MSG | Server β†’ Client | Standard message from server (payload: `messageForRendering` [here](https://github.com/sotopia-lab/sotopia-demo/blob/main/socialstream/rendering_utils.py) ) |
| CLIENT_MSG | Client β†’ Server | Standard message from client (payload: Currently not needed) |
| ERROR | Server β†’ Client | Error notification (payload: `{"type": ERROR_TYPE, "description": DESC}`) |
| START_SIM | Client β†’ Server | Initialize simulation (payload: `SimulationEpisodeInitialization`) |
| END_SIM | Client β†’ Server | End simulation (payload: not needed) |
| FINISH_SIM | Server β†’ Client | Terminate simulation (payload: not needed) |


**ERROR_TYPE**

| Error Code | Description |
|------------|-------------|
| NOT_AUTHORIZED | Authentication failure - invalid or expired token |
| SIMULATION_ALREADY_STARTED | Attempt to start a simulation that is already active |
| SIMULATION_NOT_STARTED | Operation attempted on an inactive simulation |
| RESOURCE_NOT_FOUND | Required env_id or agent_ids not found |
| SIMULATION_ERROR | Error occurred during simulation execution |
| SIMULATION_INTERRUPTED | The simulation is interruped |
| OTHER | Other unspecified errors |


**Conversation Message From the Server**
The server returns messages encapsulated in a structured format which is defined as follows:

```python
class MessageForRendering(TypedDict):
role: str # Specifies the origin of the message. Common values include "Background Info", "Environment", "{Agent Names}
type: str # Categorizes the nature of the message. Common types include: "comment", "said", "action"
content: str
```

**Implementation plan**: Currently only support LLM-LLM simulation based on [this function](https://github.com/sotopia-lab/sotopia/blob/19d39e068c3bca9246fc366e5759414f62284f93/sotopia/server.py#L108).
Loading
Loading