Skip to content
AM
All projects
AI / API Private

AI-Powered Backend & API

A FastAPI service that wraps OpenAI's chat API behind a validated, async, versioned REST endpoint, with the provider-specific code kept in its own service layer.

  • Python
  • FastAPI
  • Pydantic
  • OpenAI API
  • REST APIs

Private project, demo on request

This is client or employer work, so the source code is confidential. I can't share screenshots or credentials publicly, but I'm happy to walk you through it on a call: a live demo, the architecture and selected code.

Request a demo

Architecture

Overview

A small, reusable AI backend written in Python with FastAPI. It exposes a versioned REST endpoint that takes a user message plus the prior conversation, forwards it to OpenAI's chat completions API, and returns the assistant's reply as JSON. It is meant to be called by any frontend or other service that needs conversational AI without talking to the LLM provider directly. There is no database and no UI: the shape is client → FastAPI router → service layer → external LLM API.

System

text
Client (web app / script)
        |  POST /api/v1/chat  { message, history[] }
        v
FastAPI app (main.py)
   ├── GET /            health / liveness
   └── /api/v1 router (chat.py)
          | Pydantic validation (ChatRequest, Message)
          v
     LLMService (llm_services.py)
          | system prompt + history + new message
          v
     AsyncOpenAI client  ──>  OpenAI Chat Completions (gpt-4o-mini)
          |
          v
   { assistant_response, status }

Key design decisions

Service layer between routes and the LLM. The route handler only validates input and shapes the response; everything provider-specific (client setup, model name, system prompt, temperature) lives in LLMService. Swapping the model or provider means changing one class, not the API.

Stateless conversations. The server stores nothing. Clients send the running history with each request and the service rebuilds the message list every call. This keeps the service easy to scale out and avoids a session store for a service this size.

Async end to end. Handlers are async and use AsyncOpenAI, so a request waiting several seconds on the LLM doesn't block the event loop while other requests are served.

Validation at the edge. Pydantic models define the request contract (message plus a list of role/content messages), so malformed payloads are rejected with a 422 before any paid API call is made.

Versioned routing and config from the environment. Routes are mounted under /api/v1 so the contract can evolve without breaking callers, and the API key is read from environment variables via python-dotenv rather than committed to code.

Stack

  • Language: Python
  • API framework: FastAPI (ASGI, served with Uvicorn)
  • Validation: Pydantic models
  • LLM integration: OpenAI Python SDK (AsyncOpenAI), gpt-4o-mini
  • Config: python-dotenv environment variables
  • Storage: none (stateless)

Key Implementation Highlights

  1. Built a versioned FastAPI service exposing a POST /api/v1/chat endpoint alongside a root health route for liveness checks.

    Backend
  2. Wrapped OpenAI's chat completions API (gpt-4o-mini) in an LLMService class so route handlers never touch the SDK directly.

    AI
  3. Defined Pydantic request models that validate the message and each role/content history entry before any LLM call is made.

    Data
  4. Used async route handlers with the AsyncOpenAI client so slow LLM responses don't block other requests on the event loop.

    Performance
  5. Kept the API stateless by having clients send conversation history with each request, removing the need for a session store.

    Architecture
  6. Prepended a fixed system prompt to the client-supplied history to keep the assistant's persona consistent across turns.

    AI
  7. Loaded the OpenAI API key from environment variables with python-dotenv instead of hard-coding credentials.

    Security

Interested in the technical details?

Let's Talk