Model or dataset
Azure-Samples/rag-postgres-openai-python avatar
Azure-Samples/rag-postgres-openai-python

Azure-Samples/rag-postgres-openai-python: a RAG template for PostgreSQL rows

A RAG app to ask questions about rows in a database table. Deployable on Azure Container Apps with PostgreSQL Flexible Server.

505 stars1,054 forksPythonMIT

At a glance

What is it?
This Azure sample wires a React and FastAPI chat app to Azure OpenAI and PostgreSQL Flexible Server, with hybrid pgvector plus full text search and function calling for filters. It is a deployment template first and a library second, which shapes who should use it.
Who is it for?
Adopt this if you want a working Azure reference for retrieval over tabular rows and you are comfortable with azd, Container Apps and PostgreSQL Flexible Server. Do not adopt it if you need a stable Python package to import, or if you cannot deploy Azure OpenAI in a region that carries gpt-4o-mini and text-embedding-3-large.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What problem rag-postgres-openai-python solves, and for whom

Most retrieval examples assume your knowledge lives in documents. This one assumes it lives in a table. The README describes a web chat application with an API backend that answers questions about the rows in a PostgreSQL database table, using OpenAI chat models. The sample data in the screenshots is climbing gear, and the README's own example query is "Climbing gear cheaper than $30?", which is a row-filtering question rather than a document-summarisation question.

The audience is narrow and specific. You are building on Azure, you already have relational data, and you want a reference implementation of retrieval that mixes vector similarity with ordinary SQL predicates. The repository is an Azure sample, not a product. It ships azure.yaml, infra/, a .devcontainer/ folder and a locustfile.py, which tells you the intended consumption path is azd up rather than pip install. If you want a library you can import into an existing service, this is the wrong shape of artefact.

Hybrid search with pgvector, full text search and RRF

The retrieval mechanism is the part worth reading the source for. The README states the project does hybrid search on the PostgreSQL table using the pgvector extension for vector search plus PostgreSQL full text search, combining the two result sets with Reciprocal Rank Fusion. RRF is a rank-fusion method: each retriever produces an ordered list, and the fusion step scores documents by their reciprocal rank in each list rather than by raw similarity. That matters because cosine distance from an embedding model and a ts_rank score are not on comparable scales, so summing them directly requires tuning. RRF sidesteps the tuning at the cost of discarding score magnitude.

On top of retrieval there is a function-calling layer. The README says OpenAI function calling optionally converts user queries into query filter conditions, turning "Climbing gear cheaper than $30?" into "WHERE price < 30". So the flow is: the model decides whether the question needs a structured filter, emits it, and the backend applies it alongside the hybrid search. This is a sensible split, but it is also the most fragile part of the design, because a malformed or over-broad filter changes the answer set silently. There is no discussion in the README of validating generated SQL fragments against an allowlist of columns, which is the first thing I would add.

Installing it and running a first local question

The README gives three entry paths: GitHub Codespaces, VS Code Dev Containers, and a local environment. All three converge on the same deployment step. For a local setup the README lists the prerequisites as Azure Developer CLI, Node.js 18+, Python 3.10+, PostgreSQL 14+, pgvector, Docker Desktop and Git. Note the Python version floor: the README says 3.10+, while pyproject.toml sets ruff's target-version to py39, which is an inconsistency you should be aware of before you assume 3.9 is supported.

Fetch the template with azd, then install the Python side. The README gives these two commands, and the second installs the backend package in editable mode from src/backend:

bash
azd init -t rag-postgres-openai-python
pip install -r requirements-dev.txt
pip install -e src/backend

Deployment is three azd commands. The login step has a Codespaces fallback documented in the README, and azd up provisions resources and deploys code, prompting for two regions: one for Container Apps and PostgreSQL, another for the Azure OpenAI models.

bash
azd auth login
azd env new
azd up

For local development, copy .env.sample to .env and choose a host. The sample file defines OPENAI_CHAT_HOST and OPENAI_EMBED_HOST with the allowed values azure, openai and ollama. To point at a deployment you already made, set both to azure and fill in the endpoint and deployment names; the README says you can read the deployed values with this command:

bash
azd env get-values

One conflict to resolve on your own: .env.sample sets AZURE_OPENAI_CHAT_DEPLOYMENT to gpt-5.4, while the README's deployment section says the project uses gpt-4o-mini and text-embedding-3-large. Treat the environment output as authoritative and edit .env to match what was actually provisioned.

The embedding column setting is a migration decision, not a config detail

Three variables in .env.sample look like plumbing but are not: AZURE_OPENAI_EMBED_DIMENSIONS, AZURE_OPENAI_EMBEDDING_COLUMN and the parallel OPENAICOM_ and OLLAMA_ variants. The sample sets the Azure and OpenAI.com columns to embedding_3l with 1024 dimensions, and the Ollama column to embedding_nomic. That naming convention implies the schema carries one vector column per embedding model, so switching providers does not require re-embedding the table, it requires the right column to exist.

The README also notes, in the truncated Ollama section, that the sample data has already been embedded for nomic-embed-text. Combined with the column naming, the practical consequence is that changing embedding model means either adding a column and backfilling it, or reusing a column whose vectors came from a different model, which would produce meaningless similarity scores. The README does not document a migration script for adding a column. Check the scripts/ and infra/ directories before you assume one exists.

Where this template stops being the right tool

The deployment assumes Azure OpenAI, Azure Container Apps and Azure PostgreSQL Flexible Server, and the architecture diagram shows a user-assigned managed identity authenticating to those services with logs going to Log Analytics. That is a coherent design, and it is also a commitment. If your data must stay in an existing non-Azure PostgreSQL instance with no managed identity path, most of the infra/ directory stops being useful and you are left with the FastAPI backend as a reference.

Two other limits are visible in the repository layout. First, there are no releases: the project is consumed from the main branch, so there is no version to pin and no changelog to read when something breaks. Second, the README documents no rollback procedure for azd up. If a deployment half-succeeds, the documented recovery path is not in the README. For a sample that is acceptable; for anything you intend to run in production, that gap is yours to fill.

The model choice is also a real constraint. The README warns that gpt-4o-mini and text-embedding-3-large may not be available in all Azure regions and directs you to check region availability before selecting. A RAG sample whose deployment fails on region selection is a poor first experience, and it is the most likely reason a first azd up attempt fails.

Compared with a document-oriented RAG stack such as LlamaIndex

The obvious alternative is a general RAG framework like LlamaIndex, and the difference is not quality, it is where the retrieval logic lives. LlamaIndex gives you abstractions over document loaders, node parsers and index types, and expects you to bring your own storage and serving. This sample gives you the opposite: a fixed PostgreSQL schema, SQL-level hybrid search with RRF, and a deployed FastAPI plus React application. There is no document ingestion pipeline to configure because the rows are already in the database.

That makes the sample better when your corpus is structured, filterable and already relational, and worse when it is not. If your source material is PDFs and HTML that need chunking, LlamaIndex has the pieces and this project does not. If your source material is a products table and users ask questions with numeric constraints, the function-calling filter path here is more direct than anything a general framework gives you out of the box. Pick based on the shape of the data, not on which repository has more activity.

Maintenance, upgrade cost and the MIT licence

The repository is not archived, and the last push was on 2026-09-09, five days before this writing. That is recent, but the project has no releases, so there is no versioned upgrade path. You track main. The practical upgrade cost is therefore a diff review each time you pull, with particular attention to infra/ and azure.yaml, since those are the files most likely to change in ways that affect an existing deployment. The pyproject.toml is small: ruff with a 120-character line length, pytest with testpaths set to tests and pythonpath set to src/backend, and a ty configuration listing allowed unresolved imports for azure.ai.evaluation, rich, pgvector and evaltools. There is a pre-commit configuration and an evals/ directory, so an evaluation harness exists, though the README does not document how to run it.

The licence is MIT, per the repository metadata, and LICENSE.md is present at the top level. MIT is permissive and imposes no copyleft obligation on your own code, but note that the sample depends on Azure OpenAI, Azure Container Apps and Azure PostgreSQL Flexible Server, and those services carry their own terms and costs. The README has a Costs section; read it before running azd up against a subscription you care about. Nothing here is legal advice, and the licence text in LICENSE.md is what governs.

Editorial conclusion

Adopt this if you want a working Azure reference for retrieval over tabular rows and you are comfortable with azd, Container Apps and PostgreSQL Flexible Server. Do not adopt it if you need a stable Python package to import, or if you cannot deploy Azure OpenAI in a region that carries gpt-4o-mini and text-embedding-3-large. Before anything else, run azd env get-values after a deployment and confirm which model names and embedding column the environment actually produced, because the sample file and the README disagree.

Frequently asked questions

What does rag-postgres-openai-python actually do?

It creates a web chat application with a FastAPI backend that answers questions about rows in a PostgreSQL table using OpenAI chat models. Retrieval combines pgvector vector search with PostgreSQL full text search, fused with Reciprocal Rank Fusion.

How do I install and deploy rag-postgres-openai-python?

The README's path is azd init -t rag-postgres-openai-python, then azd auth login, azd env new and azd up. For local work you also run pip install -r requirements-dev.txt and pip install -e src/backend.

Can rag-postgres-openai-python run against OpenAI.com or a local Ollama model instead of Azure?

Yes. .env.sample defines OPENAI_CHAT_HOST and OPENAI_EMBED_HOST with the allowed values azure, openai and ollama. The README suggests llama3.1 for chat because it supports function calling, and nomic-embed-text for embeddings.

Why does rag-postgres-openai-python use an embedding column setting?

The .env.sample file sets AZURE_OPENAI_EMBEDDING_COLUMN to embedding_3l and the Ollama column to embedding_nomic, which implies one vector column per embedding model. Changing embedding model therefore means adding or backfilling a column rather than reusing an existing one.

Does rag-postgres-openai-python have versioned releases?

No releases were retrieved for the repository. It is consumed from the main branch, so there is no version to pin and no changelog to consult when upgrading.

Official sources

  1. Azure-Samples/rag-postgres-openai-python on GitHub
  2. Issues
  3. License: MIT
  4. README
Community notes

Community notes