Skip to content

Commit ffdcdfd

Browse files
committed
added fastapi-server instrucs
1 parent 24a1f1c commit ffdcdfd

5 files changed

Lines changed: 91 additions & 22 deletions

File tree

fastapi-server/.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
.venv
33
poetry.lock
44
pyproject.toml
5+
README.md
56

fastapi-server/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM --platform=linux/amd64 python:3.11
1+
FROM python:3.11
22

33

44
# Set the working directory in the container

fastapi-server/Makefile

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1+
LOCAL_ARCH=$(shell uname -m)
2+
GCLOUD_ARCH=amd64
3+
IMAGE_NAME=langroid-server
4+
TAG=latest
5+
16
server:
2-
docker build -t server .
7+
docker build --platform linux/$(LOCAL_ARCH) -t $(IMAGE_NAME):$(TAG) .
38

49
run:
5-
docker run -d -p 80:80 server
10+
docker run --env-file .env -d -p 80:80 $(IMAGE_NAME):$(TAG)
611

712
stop:
813
docker stop $(shell docker ps -q)
914

10-
gbuild:
11-
docker build -t gcr.io/langroid/langroid-server:v1 .
15+
gserver:
16+
docker build --platform=linux/$(GCLOUD_ARCH) -t gcr.io/langroid/$(IMAGE_NAME):$(TAG) .
1217

1318
gpush:
14-
docker push gcr.io/langroid/langroid-server:v1
19+
docker push gcr.io/langroid/$(IMAGE_NAME):$(TAG)

fastapi-server/README.md

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
# Setup a REST API server on GCP for a Langroid script
22

3+
Ensure that your env secrets are in this folder as a `.env` file.
4+
We will of course *not* include it in the docker image
5+
(which is why it's in the `.dockerignore` file) but we will use it
6+
for local testing by passing this file in as an env file to the uvicorn server.
7+
(See the defn of `make run` in the Makefile.)
8+
39
## local testing
410

5-
Build server using `make server`, run it with `make run`
11+
Build server using `make server`, run it with `make run`.
12+
See the definitions of these in the Makefile. Notice that
13+
we are passing in the env variables
614

715
## Curl examples to test the server locally
816

@@ -25,6 +33,13 @@ curl -X POST \
2533
```
2634
(If you omit the `-o out.txt` part, the response will be printed to the terminal.)
2735

36+
`process_file_and_data` endpoint:
37+
38+
```bash
39+
curl -X POST "http://localhost:8000/process_file_and_data/" \
40+
-F "file=@/tmp/query.txt" \
41+
-F 'complex_data={"id": 1, "item": {"name": "Item Name", "description": "A description", "quantity": 10, "tags": ["tag1", "tag2"]}, "related_items": [{"name": "Related Item 1", "description": "Description 1", "quantity": 5, "tags": ["tag3", "tag4"]}, {"name": "Related Item 2", "description": "Description 2", "quantity": 3, "tags": ["tag5", "tag6"]}]}'
42+
```
2843

2944
## Deploy to google cloud run
3045

@@ -36,20 +51,12 @@ See other details here:
3651
https://chat.openai.com/share/c34583c8-b88e-4a70-bf24-83229700c020
3752

3853

39-
Run these from within the dir where the Dockerfile is located:
40-
41-
```bash
42-
gcloud auth configure-docker
43-
docker build -t gcr.io/langroid/langroid-server:v1 .
44-
docker push gcr.io/langroid/langroid-server:v1
45-
```
46-
47-
The `build` and `push` cmds are also available via the Makefile
48-
as `make gbuild` and `make gpush` respectively.
54+
Run `make gserver`, `make gpush` from within the dir where the Dockerfile is
55+
located.
4956

5057
Go to Google Cloud Run Service and create a new service,
51-
selecting the latest version of the pushed docker image above:
52-
`gcr.io/langroid/langroid-server:v1`
58+
selecting the latest version of the pushed docker image above, e.g.:
59+
`gcr.io/langroid/langroid-server:latest`
5360

5461
When setting up the service:
5562
- ensure you select the same port number as in the Dockerfile, e.g. 80.
@@ -61,6 +68,33 @@ If the service fails to start due to an error like `uvicorn: exec format error`,
6168
then you may be able to fix it by explicitly choosing an architecture
6269
in the Dockerfile, e.g. `linux/amd64` (which we chose in the Dockerfile).
6370

71+
### Creating secrets in google cloud
72+
Some commands for quick reference:
73+
74+
```bash
75+
gcloud secrets create openai-api-key --replication-policy="automatic"
76+
echo -n "your-openai-api-key" | gcloud secrets versions add openai-api-key --data-file=-
77+
```
78+
79+
After creating your secret and adding its value, you may need to set appropriate
80+
permissions for the secret. Use gcloud secrets add-iam-policy-binding to grant access
81+
to the secret:
82+
83+
```bash
84+
gcloud secrets add-iam-policy-binding openai-api-key \
85+
--member="serviceAccount:langroid-docai-sa@langroid.iam.gserviceaccount.com" \
86+
--role="roles/secretmanager.secretAccessor"
87+
```
88+
89+
To expose one of these as environment var named `OPENAI_API_KEY` in the cloud run
90+
service:
91+
92+
```bash
93+
gcloud run services update langroid-server \
94+
--update-secrets OPENAI_API_KEY=openai-api-key:latest \
95+
--region=us-east4
96+
```
97+
6498
## Test GCP endpoints
6599

66100
Same curl cmds as above, but use the endpoint url from the GCP Cloud Run service,

fastapi-server/app.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from typing import Any
2-
from fastapi import FastAPI, File, UploadFile
1+
from typing import Any, Dict, List
2+
from fastapi import FastAPI, File, UploadFile, Form
33
from fastapi.responses import FileResponse
4-
from pydantic import BaseModel
4+
from pydantic import BaseModel, Json
55
import uvicorn
66
import os
77
import langroid as lr
@@ -10,6 +10,19 @@
1010
class TextInput(BaseModel):
1111
text: str
1212

13+
# Define your Pydantic models for the complex payload
14+
class Item(BaseModel):
15+
name: str
16+
description: str
17+
quantity: int
18+
tags: List[str]
19+
20+
class ComplexItem(BaseModel):
21+
id: int
22+
item: Item
23+
related_items: List[Item]
24+
25+
1326
class Server:
1427
def __init__(self):
1528
self.setup()
@@ -60,6 +73,22 @@ def process_text(text_input: TextInput) -> Any:
6073
result = server.serve_text(text_input.text)
6174
return {"message": result, "status": "ok"}
6275

76+
@app.post("/process_file_and_data/")
77+
async def process_file_and_data(
78+
file: UploadFile = File(...),
79+
complex_data: Json[ComplexItem] = Form(...)
80+
) -> Dict[str, Any]:
81+
# You can now access the file and the complex data
82+
# For example, save the file and process the complex data
83+
# Here, just return a message indicating success for demonstration
84+
85+
return {
86+
"message": "Received file and complex data successfully!",
87+
"file_name": file.filename,
88+
"complex_data_id": complex_data.id,
89+
"complex_data_item_name": complex_data.item.name
90+
}
91+
6392
# This port number must match the port number in the Dockerfile
6493
if __name__ == "__main__":
6594
uvicorn.run(app, host="0.0.0.0", port=80)

0 commit comments

Comments
 (0)