Skip to content

1. Explore the Codebase

Let's look at how the FastAPI application is implemented in the src/api/main.py file. Open it now in Visual Studio Code and let's explore the code in sections. You can also expand the section below to see the code inline.

FASTAPI application server code

src/api/main.py
 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
import os
from pathlib import Path
from fastapi import FastAPI
from dotenv import load_dotenv
from prompty.tracer import trace
from prompty.core import PromptyStream, AsyncPromptyStream
from fastapi.responses import StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from tracing import init_tracing

from contoso_chat.chat_request import get_response

base = Path(__file__).resolve().parent

load_dotenv()
tracer = init_tracing()

app = FastAPI()

code_space = os.getenv("CODESPACE_NAME")
app_insights = os.getenv("APPINSIGHTS_CONNECTIONSTRING")

if code_space: 
    origin_8000= f"https://{code_space}-8000.app.github.dev"
    origin_5173 = f"https://{code_space}-5173.app.github.dev"
    ingestion_endpoint = app_insights.split(';')[1].split('=')[1]

    origins = [origin_8000, origin_5173, os.getenv("SERVICE_ACA_URI")]
else:
    origins = [
        o.strip()
        for o in Path(Path(__file__).parent / "origins.txt").read_text().splitlines()
    ]
    origins = ['*']

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.get("/")
async def root():
    return {"message": "Hello World"}


@app.post("/api/create_response")
@trace
def create_response(question: str, customer_id: str, chat_history: str) -> dict:
    result = get_response(customer_id, question, chat_history)
    return result

# TODO: fix open telemetry so it doesn't slow app so much
FastAPIInstrumentor.instrument_app(app)
  1. Import the chat function (line 11). The get_response function is the entry point into our Contoso Chat implementation. It expects a customer ID, a question, and the chat history, and returns a text response.

  2. Instantiate the app server (line 19-43). We use the FastAPI application server, creating it with default configurations and configuring it to allow requests from specified origins (including GitHub Codespaces hosted clients).

  3. Define a default route (line 46). The "/" route maps to the base URL for the application server.

    • It accepts GET requests with no parameters (equivalent to a browser site visit).
    • It returns a JSON response with a "Hello World" message.
    • This serves as a "health check" for the app server, verifying it's alive (e.g., during setup).
  4. Define the copilot route (line 51). The "/api/create_response" route maps to the endpoint where we can invoke the Contoso Chat implementation.

    • It accepts POST requests from clients and extracts required parameters.
    • It invokes our copilot get_request function with those parameters.
    • It returns the copilot response to the client.

Now all we need to do is run the FastAPI server, and have it listen for incoming requests from clients on these two API routes ("/" for health checks and "/api/create_response" for Contoso Chat). In the next section, we'll see how to do this locally for rapid prototyping and testing.


CONGRATULATIONS. You just reviewed the FastAPI application structure!