Skip to content
Snippets Groups Projects
Commit 50e1864a authored by Marcus Schiesser's avatar Marcus Schiesser
Browse files

added streaming fastapi template

parent 37ac88fc
No related branches found
No related tags found
No related merge requests found
Showing
with 162 additions and 0 deletions
__pycache__
poetry.lock
storage
This is a [LlamaIndex](https://www.llamaindex.ai/) project using [FastAPI](https://fastapi.tiangolo.com/) bootstrapped with [`create-llama`](https://github.com/run-llama/LlamaIndexTS/tree/main/packages/create-llama).
## Getting Started
First, setup the environment:
```
poetry install
poetry shell
```
Second, run the development server:
```
python main.py
```
Then call the API endpoint `/api/chat` to see the result:
```
curl --location 'localhost:8000/api/chat' \
--header 'Content-Type: application/json' \
--data '{ "messages": [{ "role": "user", "content": "Hello" }] }'
```
You can start editing the API by modifying `app/api/routers/chat.py`. The endpoint auto-updates as you save the file.
Open [http://localhost:8000/docs](http://localhost:8000/docs) with your browser to see the Swagger UI of the API.
## Learn More
To learn more about LlamaIndex, take a look at the following resources:
- [LlamaIndex Documentation](https://docs.llamaindex.ai) - learn about LlamaIndex.
You can check out [the LlamaIndex GitHub repository](https://github.com/run-llama/llama_index) - your feedback and contributions are welcome!
import logging
import os
from typing import List
from fastapi import APIRouter, Depends, HTTPException, Request, status
from llama_index import (
StorageContext,
load_index_from_storage,
SimpleDirectoryReader,
VectorStoreIndex,
)
from llama_index.llms.base import MessageRole
from pydantic import BaseModel
from sse_starlette.sse import EventSourceResponse
STORAGE_DIR = "./storage" # directory to cache the generated index
DATA_DIR = "./data" # directory containing the documents to index
chat_router = r = APIRouter()
class Message(BaseModel):
role: MessageRole
content: str
class _ChatData(BaseModel):
messages: List[Message]
def get_index():
logger = logging.getLogger("uvicorn")
# check if storage already exists
if not os.path.exists(STORAGE_DIR):
logger.info("Creating new index")
# load the documents and create the index
documents = SimpleDirectoryReader(DATA_DIR).load_data()
index = VectorStoreIndex.from_documents(documents)
# store it for later
index.storage_context.persist(STORAGE_DIR)
logger.info(f"Finished creating new index. Stored in {STORAGE_DIR}")
else:
# load the existing index
logger.info(f"Loading index from {STORAGE_DIR}...")
storage_context = StorageContext.from_defaults(persist_dir=STORAGE_DIR)
index = load_index_from_storage(storage_context)
logger.info(f"Finished loading index from {STORAGE_DIR}")
return index
@r.post("/")
async def chat(
request: Request, data: _ChatData, index: VectorStoreIndex = Depends(get_index)
) -> Message:
# check preconditions
if len(data.messages) == 0:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="No messages provided",
)
lastMessage = data.messages.pop()
if lastMessage.role != MessageRole.USER:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Last message must be from user",
)
# query chat engine
chat_engine = index.as_chat_engine()
response = chat_engine.stream_chat(lastMessage.content, data.messages)
# stream response
async def event_generator():
for token in response.response_gen:
# If client closes connection, stop sending events
if await request.is_disconnected():
break
yield token
return EventSourceResponse(event_generator())
File added
__pycache__
storage
import os
import uvicorn
from app.api.routers.chat import chat_router
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origin = os.getenv("CORS_ORIGIN")
if origin:
app.add_middleware(
CORSMiddleware,
allow_origins=[origin],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(chat_router, prefix="/api/chat")
if __name__ == "__main__":
uvicorn.run(app="main:app", host="0.0.0.0", reload=True)
[tool.poetry]
name = "llamaindex-fastapi-streaming"
version = "0.1.0"
description = ""
authors = ["Marcus Schiesser <mail@marcusschiesser.de>"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.11,<3.12"
fastapi = "^0.104.1"
uvicorn = { extras = ["standard"], version = "^0.23.2" }
llama-index = "^0.8.56"
pypdf = "^3.17.0"
sse-starlette = "^1.6.5"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment