Spaces:
Sleeping
Sleeping
File size: 7,963 Bytes
fa37f46 9c9ef1d fa37f46 9c9ef1d fa37f46 9c9ef1d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | ---
title: MyVillage Activity Generation API
emoji: 🌱
colorFrom: green
colorTo: blue
sdk: docker
app_port: 7860
pinned: false
---
# MyVillage Activity Generation API
One lightweight **FastAPI** wrapper around three separately deployed Hugging Face Spaces:
1. Progression: what the villager needs to do next.
2. Composition: activity title and description from the progression plan.
3. Instruction: step-by-step instructions from the progression and composition results.
Only the **final title, description and instructions** leave this API. No Qwen weights, GGUF files, Transformers, or GPU are needed in this Space.
## Endpoint
`POST /generate-activity` with this JSON body:
```json
{
"version": "v1",
"knowledge_submission": "I reviewed 25 saved chatbot conversations. I noticed the refund responses sometimes contradicted the policy, but I have not systematically documented the errors.",
"wisdom": {
"content": "Testing systems requires comparing observations with expected outcomes.",
"chapterTitle": "Testing With Purpose",
"BookTypeName": "Personal Records",
"BookType": "personal_record"
},
"village_goal": "Build and evaluate a reliable customer support chatbot",
"previous_activity_title": "Test Chatbot Conversations"
}
```
Response shape (generated text varies):
```json
{
"output": {
"activity_title": "Evaluate Chatbot Response Accuracy",
"activity_description": "Review saved chatbot conversations to identify recurring errors in responses.",
"instructions": [
"Review the 25 saved chatbot conversations.",
"Compare responses with expected answers.",
"List recurring errors by category."
]
}
}
```
Input wisdom uses the **exact existing** field names `content`, `chapterTitle`, `BookTypeName`, `BookType`. The wrapper does not synthesize wisdom from the current knowledge submission. Progression fields are passed through: **no `success_evidence` field is fabricated or required**.
Other endpoints: `GET /health` (liveness), `GET /docs` (Swagger), `GET /openapi.json`.
## Deploy on Hugging Face Spaces (Docker)
1. Create a **Docker** Space named e.g. `mjpsm/activity-generation-api`.
2. Copy the entire repository content into that Space (including `Dockerfile`, `app/`, `requirements.txt`, and this `README.md`).
3. Under **Settings → Variables and secrets**, set the three `*_API_URL` variables if needed, and optionally set `API_KEY` as a secret. Set `HF_TOKEN` as a secret only if the upstream Spaces require authentication.
4. Wait for Space status **Running**, then open `https://mjpsm-activity-generation-api.hf.space/docs` (assuming that is the Space name you selected).
5. Use **Try it out** for `POST /generate-activity`, or issue the cURL request below.
### Important: Live contract verification
The three Space repository identities have been checked, **but their live OpenAPI JSON could not be fetched during development**. This project does **not** claim the live POST paths or exact intermediate request bodies were verified. To avoid inventing endpoint paths, each default API URL points to its **base**; on first use, the wrapper asks that Space for `/openapi.json` and automatically selects the POST route when unambiguous.
If the upstream Space has multiple POST routes, set its URL to the **full POST endpoint** from that Space's `/docs`, such as `https://...hf.space/<actual-post-path>` (not `/docs`).
### Intermediate request body contract
By default, this wrapper uses:
- **Progression** request: original input JSON as sent to `/generate-activity`.
- **Composition** request: `{"progression": <unwrapped progression object>}`.
- **Instruction** request: `{"progression": <unwrapped progression object>, "composition": {"activity_title": "...", "activity_description": "..."}}`.
Common response envelopes `{"output": ...}` and `{"progression": ...}` are unwrapped before forwarding. Composition requires non-empty `activity_title` and `activity_description`. Instruction requires a nonempty array of nonblank strings in `instructions`.
If a deployed Space's actual request schema nests its inputs differently, use the corresponding **Variables** (no code edits needed):
| Variable | Value | Request body |
|---|---|---|
| `COMPOSITION_INPUT_STYLE` | `direct` (default) | `{"progression": {...}}` |
| | `input` | `{"input": {"progression": {...}}}` |
| | `bare` | progression object directly |
| `INSTRUCTION_INPUT_STYLE` | `direct` (default) | `{"progression": {...}, "composition": {"activity_title": "...", "activity_description": "..."}}` |
| | `nested_output` | `{"progression": {...}, "composition": {"output": {"activity_title": "...", "activity_description": "..."}}}` |
| | `input` | wraps the `direct` request in `{"input": ...}` |
| | `input_nested_output` | wraps the `nested_output` request in `{"input": ...}` |
A 502 `upstream_http_error` with HTTP 422 often indicates a request shape mismatch; check the upstream Swagger docs and change the applicable variable. Avoid silently retrying arbitrary alternate bodies or hiding schema mismatches.
### Calling your wrapper
```bash
curl -X POST 'http://localhost:7860/generate-activity' \
-H 'Content-Type: application/json' \
-d '{
"version": "v1",
"knowledge_submission": "I tested the chatbot in 25 conversations but have not documented its recurring errors.",
"wisdom": {
"content": "Compare actual outputs against expectations when testing.",
"chapterTitle": "Test With Purpose",
"BookTypeName": "Personal Records",
"BookType": "personal_record"
},
"village_goal": "Build a reliable customer service chatbot",
"previous_activity_title": "Test Chatbot Conversations"
}'
```
If you set the `API_KEY` secret, also include `-H 'X-API-Key: your-secret-key'` in client calls. Treat this like a server-side key; don't embed it in public web frontend JavaScript.
## Run locally
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txt
cp .env.example .env # optional reference; configure env vars in shell to apply them
uvicorn app.main:app --reload --port 7860
```
**Note:** This template intentionally does not load `.env` automatically, to avoid another dependency. To use `.env` locally, export the file's values into your shell or use a runner that reads dotenv files.
Run tests:
```bash
pytest -q
```
The tests mock all upstream model APIs. They validate orchestration, payload shapes, retries/errors, and output validation without inference costs. **They are not live end-to-end verification**.
## Error handling and safety
- Input validation returns **422** before calling any model.
- Upstream errors return **502/503**, and exhausted timeouts return **504**. The error contains the failing `stage` and a short code, but **not submitted knowledge or model output**.
- Each model call is sequential; the wrapper stops on any error (no partial activities).
- Transient **429/502/503/504**, timeouts, and network failures are retried once by default; HTTP 422 contract errors are **not** retried.
- Set `READ_TIMEOUT_SECONDS` for cold Spaces; default 240s. `MAX_ATTEMPTS` defaults to 2.
- Logs include stage names, timing and a request identifier, not user input.
- `GET /health` only checks the wrapper. It does not prove the three upstream Spaces are awake.
- Configure `API_KEY` and keep upstream `HF_TOKEN` secrets private before production use.
## Check the live APIs before your first end-to-end test
On a machine with internet access, run:
```bash
python scripts/inspect_upstreams.py
```
This performs **read-only GET requests** to the three Spaces' OpenAPI documents. It shows their actual POST URLs, top-level request properties, and required properties without making inference calls. Compare its output with the `COMPOSITION_INPUT_STYLE` and `INSTRUCTION_INPUT_STYLE` settings above. You can set the three service URLs in the shell if they have changed.
|