ema-frontend-demo / docs /modelorchestrator-api.md
harryagasi
feat: repoint chat, chatroom & feedback to golang service
5042d8c
|
Raw
History Blame Contribute Delete
16.5 kB
# Model Orchestrator Service β€” API Documentation
**Version**: 1.0
**Base URL**: `http://localhost:8090` (local) β€” configured via `SERVICE_RUNTIME_HOST`
**Content-Type**: `application/json`
---
## Authentication
All endpoints under `/api/*` require a JWT Bearer token.
```
Authorization: Bearer <JWT_TOKEN>
```
The token must contain the following claims: `TenantId`, `UserId`, `Email`, `UniqueName`, `FullName`.
---
## Response Format
### Success
All successful responses are wrapped in a consistent envelope:
```json
{
"data": { ... }
}
```
### Error
```json
{
"error_message": "Human-readable description",
"error_code": "machine.readable.code"
}
```
### HTTP Status Codes
| Code | Meaning |
|------|---------|
| 200 | Success |
| 400 | Bad request / validation error |
| 401 | Unauthorized β€” missing or invalid token |
| 500 | Internal server error |
---
## Endpoints Overview
| Method | Path | Description | Auth |
|--------|------|-------------|------|
| GET | `/health/ready` | Readiness probe | No |
| GET | `/health/live` | Liveness probe | No |
| GET | `/api/room` | Get all rooms | Yes |
| PUT | `/api/room/:room_id` | Update room name | Yes |
| PATCH | `/api/room/:room_id` | Delete a room | Yes |
| GET | `/api/room/:room_id/chat` | Get all chats in a room | Yes |
| POST | `/api/chat` | Create a new chat | Yes |
| POST | `/api/chat/:chat_id/retry` | Retry a failed chat | Yes |
| GET | `/api/chat/:chat_id/status` | Get chat processing status | Yes |
| POST | `/api/chat/:chat_id/feedback` | Submit feedback for a chat | Yes |
| GET | `/api/chatbot/helper_prompt` | Get equipment helper prompts | Yes |
---
## Health
### GET `/health/ready`
Returns `200 Ok` when the service is ready to receive traffic. No auth required.
### GET `/health/live`
Returns `200 Ok` when the service process is alive. No auth required.
---
## Room
Rooms are conversation containers. Each room holds a list of chat exchanges belonging to a user.
---
### GET `/api/room`
Get all rooms belonging to the authenticated user.
**Request**: No body, no query parameters.
**Response `200`**:
```json
{
"data": [
{
"id": "string",
"name": "string"
}
]
}
```
| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Unique room identifier |
| `name` | string | Display name of the room |
**Error responses**:
| Code | `error_code` | Description |
|------|-------------|-------------|
| 500 | `modelorchestrator.room.get.error` | Failed to retrieve rooms |
---
### PUT `/api/room/:room_id`
Rename an existing room.
**Path parameter**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `room_id` | string | Yes | ID of the room to update |
**Request body**:
```json
{
"name": "string"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | New name for the room |
**Response `200`**:
```json
{
"data": {
"room_id": "string"
}
}
```
**Error responses**:
| Code | `error_code` | Description |
|------|-------------|-------------|
| 400 | `modelorchestrator.room.update.errorvalidation` | Invalid or missing request body |
| 500 | `modelorchestrator.room.update.error` | Failed to update room |
---
### PATCH `/api/room/:room_id`
Soft-delete a room.
**Path parameter**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `room_id` | string | Yes | ID of the room to delete |
**Request body**: None
**Response `200`**:
```json
{
"data": {
"room_id": "string"
}
}
```
**Error responses**:
| Code | `error_code` | Description |
|------|-------------|-------------|
| 500 | `modelorchestrator.room.delete.error` | Failed to delete room |
---
### GET `/api/room/:room_id/chat`
Get the full chat history for a specific room.
**Path parameter**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `room_id` | string | Yes | ID of the room |
**Request body**: None
**Response `200`**:
```json
{
"data": [
{
"id": "string",
"question": "any",
"answer_text": "any | null",
"status": "string",
"feedback_status": "string | null",
"feedback_reason": "string | null"
}
]
}
```
| Field | Type | Nullable | Description |
|-------|------|----------|-------------|
| `id` | string | No | Chat entry ID |
| `question` | any | No | The question that was submitted (can be string or object) |
| `answer_text` | any | Yes | The answer returned by the AI. `null` if still processing |
| `status` | string | No | Processing status of the chat. See [Chat Status Values](#chat-status-values) |
| `feedback_status` | string | Yes | Feedback given by user, if any |
| `feedback_reason` | string | Yes | Reason for the feedback, if any |
**Error responses**:
| Code | `error_code` | Description |
|------|-------------|-------------|
| 500 | `modelorchestrator.room.chat.error` | Failed to retrieve room chats |
---
## Chat
A chat represents a single question–answer exchange within a room. Creating a chat triggers the AI processing asynchronously β€” use the status endpoint to poll for completion.
---
### POST `/api/chat`
Create a new chat (submit a question to the AI).
If `room_id` is empty, a new room will be created automatically and its ID is returned in the response.
**Request body**:
```json
{
"agent": "string",
"req_plot_object": false,
"room_id": "string",
"question": "any"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `agent` | string | Yes | Identifier of the AI agent to use |
| `req_plot_object` | boolean | Yes | Set `true` if the response should include a plot/chart object |
| `room_id` | string | Yes | ID of the room to post the chat in. Pass an empty string `""` to auto-create a room |
| `question` | any | Yes | The question or prompt. Can be a plain string or a structured object depending on the agent |
**Response `200`**:
```json
{
"data": {
"room_id": "string",
"room_name": "string",
"chat_id": "string"
}
}
```
| Field | Type | Description |
|-------|------|-------------|
| `room_id` | string | The room this chat belongs to (auto-generated if not provided) |
| `room_name` | string | Display name of the room |
| `chat_id` | string | ID of the newly created chat. Use this to poll status and submit feedback |
**Error responses**:
| Code | `error_code` | Description |
|------|-------------|-------------|
| 400 | `modelorchestrator.chat.create.errorvalidation` | Invalid or missing request body |
| 500 | `modelorchestrator.chat.create.error` | Failed to create chat |
---
### POST `/api/chat/:chat_id/retry`
Retry a chat that failed or got stuck. Resubmits the original question.
**Path parameter**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `chat_id` | string | Yes | ID of the chat to retry |
**Request body**: None
**Response `200`**:
```json
{
"data": {
"room_id": "string",
"chat_id": "string"
}
}
```
**Error responses**:
| Code | `error_code` | Description |
|------|-------------|-------------|
| 500 | `modelorchestrator.chat.retry.error` | Failed to retry chat |
---
### GET `/api/chat/:chat_id/status`
Poll the processing status of a chat. Use this after creating a chat to determine when the answer is ready.
**Path parameter**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `chat_id` | string | Yes | ID of the chat |
**Request body**: None
**Response `200`**:
```json
{
"data": {
"chat_id": "string",
"status": "string"
}
}
```
**Error responses**:
| Code | `error_code` | Description |
|------|-------------|-------------|
| 500 | `modelorchestrator.chat.getstatus.error` | Failed to retrieve chat status |
#### Chat Status Values
| Status | Description |
|--------|-------------|
| `pending` | Chat has been created, waiting to be processed |
| `processing` | AI is currently generating a response |
| `completed` | Response is ready β€” fetch via `GET /api/room/:room_id/chat` |
| `failed` | Processing failed β€” use retry endpoint |
> **Polling recommendation**: Poll every 2–3 seconds. Stop when status is `completed` or `failed`.
---
### POST `/api/chat/:chat_id/feedback`
Submit user feedback (thumbs up/down and reason) for a completed chat.
**Path parameter**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `chat_id` | string | Yes | ID of the chat to give feedback on |
**Request body**:
```json
{
"status": "string",
"reason": "string"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `status` | string | Yes | Feedback rating (e.g. `"positive"`, `"negative"`) |
| `reason` | string | Yes | Explanation for the feedback |
**Response `200`**:
```json
{
"data": {
"id": "string"
}
}
```
| Field | Type | Description |
|-------|------|-------------|
| `id` | string | ID of the created feedback record |
**Error responses**:
| Code | `error_code` | Description |
|------|-------------|-------------|
| 400 | `modelorchestrator.chat.createfeedback.errorvalidation` | Invalid or missing request body |
| 500 | `modelorchestrator.chat.createfeedback.error` | Failed to submit feedback |
---
## Chatbot
### GET `/api/chatbot/helper_prompt`
Get a structured list of equipment suggestions to help users construct prompts. The response is a 4-level nested map: `site_id β†’ section β†’ model β†’ eqm_no β†’ [equipment list]`.
**Query parameters**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `topic` | string | Yes | Topic category. Must be one of the allowed values below |
| `year` | integer | Yes | The year to filter data by (e.g. `2024`) |
**Allowed `topic` values**:
| Value | Description |
|-------|-------------|
| `pa performance` | PA performance analysis |
| `bad actor` | Bad actor identification |
| `pareto` | Pareto analysis |
| `inspection` | Inspection data |
| `backlog` | Maintenance backlog |
| `planning` | Planning analysis |
| `execution` | Execution analysis |
**Response `200`**:
```json
{
"data": {
"<site_id>": {
"<section>": {
"<model>": {
"<eqm_no>": ["equipment_name_1", "equipment_name_2"]
}
}
}
}
}
```
**Example**:
```json
{
"data": {
"SITE_A": {
"MECHANICAL": {
"PUMP": {
"P-001": ["P-001A", "P-001B"]
}
}
}
}
}
```
**Error responses**:
| Code | `error_code` | Description |
|------|-------------|-------------|
| 400 | `helper.prompt.validation.topic` | `topic` is missing or not one of the allowed values |
| 400 | `helper.prompt.validation.year` | `year` query parameter is missing |
| 400 | `helper.prompt.validation.year.format` | `year` is not a valid integer |
| 500 | `helper.prompt.service.error` | Failed to retrieve helper prompt data |
---
## Typical Frontend Flow
Below is the recommended sequence for a full chat interaction:
```
1. GET /api/room β†’ fetch existing rooms for sidebar
2. POST /api/chat β†’ submit question (use room_id="" for new room)
← returns { room_id, room_name, chat_id }
3. GET /api/chat/:chat_id/status β†’ poll every 2–3s until status = "completed" or "failed"
4. GET /api/room/:room_id/chat β†’ fetch full chat history including the answer
5. POST /api/chat/:chat_id/feedback β†’ (optional) submit user rating
6. POST /api/chat/:chat_id/retry β†’ (if status = "failed") retry
```
---
## Error Code Reference
All error responses follow this format:
```json
{
"error_message": "Human-readable description",
"error_code": "machine.readable.code"
}
```
### Authentication Errors
These errors are returned before any endpoint logic runs, when the JWT token is missing, malformed, or invalid.
| HTTP | `error_code` | `error_message` | Cause |
|------|-------------|-----------------|-------|
| 401 | `error.cred.missing` | Authorization creds missing | `Authorization` header not present in request |
| 401 | `error.cred.incomplete` | Authorization cred incomplete | Header present but not in `Bearer <token>` format |
| 401 | `error.cred.invalid` | Authorization cred invalid | JWT token cannot be parsed or is malformed |
| 401 | `error.cred.missingAttribute` | Authorization cred attribute missing | Token is valid but missing required claims (`tenantId` or `userId`) |
| 401 | `error.database.connectionfailure` | Unable to establish connection to tenant database | Service could not open a DB connection for the tenant derived from the token |
### Room Errors
| HTTP | `error_code` | `error_message` | Endpoint | Cause |
|------|-------------|-----------------|----------|-------|
| 500 | `modelorchestrator.room.gettenant.error` | Unable to get tenant context | All room endpoints | Internal error reading tenant context from middleware |
| 400 | `modelorchestrator.room.update.errorvalidation` | Unable to read input | `PUT /api/room/:room_id` | Request body is missing or not valid JSON |
| 500 | `modelorchestrator.room.update.error` | Unable to update room | `PUT /api/room/:room_id` | Database error while updating the room |
| 500 | `modelorchestrator.room.delete.error` | Unable to get room chats | `PATCH /api/room/:room_id` | Database error while deleting the room |
| 500 | `modelorchestrator.room.get.error` | Unable to get rooms | `GET /api/room` | Database error while fetching room list |
| 500 | `modelorchestrator.room.chat.error` | Unable to get room chats | `GET /api/room/:room_id/chat` | Database error while fetching chat history |
### Chat Errors
| HTTP | `error_code` | `error_message` | Endpoint | Cause |
|------|-------------|-----------------|----------|-------|
| 500 | `modelorchestrator.chat.gettenant.error` | Unable to get tenant context | All chat endpoints | Internal error reading tenant context from middleware |
| 400 | `modelorchestrator.chat.create.errorvalidation` | Unable to read input | `POST /api/chat` | Request body is missing or not valid JSON |
| 500 | `modelorchestrator.chat.create.error` | Unable to create chat | `POST /api/chat` | Database error while creating the chat record |
| 500 | `modelorchestrator.chat.retry.error` | Unable to retry chat | `POST /api/chat/:chat_id/retry` | Chat not found or database error during retry |
| 500 | `modelorchestrator.chat.getstatus.error` | Unable to get chat status | `GET /api/chat/:chat_id/status` | Database error while fetching chat status |
| 400 | `modelorchestrator.chat.createfeedback.errorvalidation` | Unable to read input | `POST /api/chat/:chat_id/feedback` | Request body is missing or not valid JSON |
| 500 | `modelorchestrator.chat.createfeedback.error` | Unable to get chat status | `POST /api/chat/:chat_id/feedback` | Database error while saving feedback |
### Chatbot Errors
| HTTP | `error_code` | `error_message` | Endpoint | Cause |
|------|-------------|-----------------|----------|-------|
| 500 | `modelorchestrator.prompt.gettenant.error` | Unable to get tenant context | `GET /api/chatbot/helper_prompt` | Internal error reading tenant context from middleware |
| 400 | `helper.prompt.validation.topic` | Invalid topic provided | `GET /api/chatbot/helper_prompt` | `topic` query param is missing or not one of the 7 allowed values |
| 400 | `helper.prompt.validation.year` | Year is required | `GET /api/chatbot/helper_prompt` | `year` query param is not provided |
| 400 | `helper.prompt.validation.year.format` | Invalid year format | `GET /api/chatbot/helper_prompt` | `year` query param is not a valid integer |
| 500 | `helper.prompt.service.error` | Failed to get helper prompt | `GET /api/chatbot/helper_prompt` | Database error while fetching helper prompt data |
### System Errors
| HTTP | `error_code` | `error_message` | Cause |
|------|-------------|-----------------|-------|
| 500 | `error.internalservererror` | Internal Server Error | Unhandled panic in the service β€” logged server-side with full stack trace |
---
## CORS
CORS is enabled globally. All origins are allowed and credentials are supported.
```
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, OPTIONS, GET, PUT, PATCH
```