Skip to course content
Free FastAPI backend course

FastAPI for AI Backend Development

Unit 08.03: Where the model calls live

One file should know which model provider you use.

The vendor boundary

Four files with what each knows.

The code lists them.

STRUCTURE = [
    ("app/routers/classify.py", "HTTP only", "validates, calls the service"),
    ("app/services/classify.py", "logic",    "builds the prompt, calls the client"),
    ("app/clients/model.py",     "boundary", "the only file that knows the provider"),
    ("app/models.py",            "contract", "request and response shapes"),
]
print(f"{'file':28} {'role':10} contains")
for path, role, contains in STRUCTURE:
    print(f"{path:28} {role:10} {contains}")

print("""
One file knows the provider. Swapping model vendors, adding a retry, or
injecting a fake for tests is a change in `clients/model.py` and nowhere else.

The service knows there is a model and not which one, which is what keeps the
logic testable without a network.
""")

Swapping vendors, adding a retry or injecting a fake is a change in the client file and nowhere else. The service knows there is a classifier and not which one.

That is also what makes the offline test suite possible. The service can be handed a fake that satisfies the same shape, and every rule in it is exercised without a network.

The mistake this prevents

The mistake is calling the provider's SDK directly from the service because it is one line. The vendor's types then spread through your codebase, and a change of provider becomes a change everywhere those types appear.

Takeaway

Confine the provider to one client module. The service depends on a shape, which is what makes both vendor changes and offline testing cheap.