Skip to main content

LLM-backed, structured JSON output, schema-aware natural language queries for Django ORM

Project description

Django YOLOQuery

LLM‑Based Queries for the Django ORM

⚠️ This is just a Proof-of-Concept

PyPI version Python versions Django versions


Why?

I want to see how badly LLMs can be integrated into our system


TL;DR

authors = Author.objects.ai_query("get all authors named John")
books   = Book.objects.ai_query("books published after 2020 by American authors")
recent  = Author.objects.ai_query("authors with books published in the last 5 years")

Install

pip install django-yoloquery

Configure

Add to INSTALLED_APPS and set a few knobs in settings.py.

INSTALLED_APPS = [
    # ... your apps ...
    'django_yoloquery',
]

# Required: OpenAI API key (or set env OPENAI_API_KEY)
YOLOQUERY_OPENAI_API_KEY = "sk-..."

# Optional (shown with defaults)
YOLOQUERY_SCHEMA_DEPTH = 1            # how far to traverse relations
YOLOQUERY_INCLUDE_REVERSE = True      # include reverse relations (related_name / _set)
YOLOQUERY_LLM_MODEL = "gpt-4o-mini"   # pick your OpenAI model
YOLOQUERY_AUTO_INSTALL = ["myapp.*"]  # auto‑YOLO patch models

🔑 If YOLOQUERY_OPENAI_API_KEY is not set, YOLOQuery falls back to the OPENAI_API_KEY environment variable.


Manual Wiring (if you don’t want auto‑patch)

from django.db import models
from django_yoloquery import YoloManager

class Author(models.Model):
    name       = models.CharField(max_length=200)
    country    = models.CharField(max_length=100)
    birth_date = models.DateField()

    objects = YoloManager()  # manual install

class Book(models.Model):
    title          = models.CharField(max_length=200)
    authors        = models.ManyToManyField(Author, related_name="books")
    published_date = models.DateField()
    isbn           = models.CharField(max_length=13)

Auto‑Installation Patterns

YOLOQuery can monkey‑patch all the things at startup. Patterns are case‑sensitive app labels; model name matching is case‑insensitive.

YOLOQUERY_AUTO_INSTALL = [
    "myapp.*",        # all models in myapp
    "blog.Post",      # just that one model
    "*",              # YOLO EVERYTHING (seriously?)
]

When auto‑installed:

  • The model’s default manager (.objects) is replaced with a YOLO manager.
  • The original manager is saved as ._orig_objects.
  • A .yolo alias also points at the YOLO manager because branding.

What the LLM Sees

YOLOQuery builds a JSON description of your model + related models (depth configurable, reverse rels optional). Example schema snippet for Author:

{
  "root_model": "Author",
  "app_label": "myapp",
  "models": {
    "Author": {
      "fields": {
        "name":    {"type": "CharField", "null": false},
        "country": {"type": "CharField", "null": false},
        "birth_date": {"type": "DateField", "null": false}
      },
      "relationships": {
        "books": {"type": "REV", "to": "Book"}
      }
    },
    "Book": {
      "fields": {
        "title": {"type": "CharField", "null": false},
        "published_date": {"type": "DateField", "null": false}
      },
      "relationships": {
        "authors": {"type": "M2M", "to": "Author"}
      }
    }
  }
}

Structured JSON Contract

The model must return JSON like:

{
  "status": "ok",
  "logic": "and",             // or "or"
  "filters": [
    {"path": "name", "op": "iexact", "value": "John"},
    {"path": "books__published_date", "op": "gt", "value": "2020-01-01"}
  ],
  "order_by": ["-published_date"],  // optional
  "limit": 10                        // optional
}

If the request can’t be translated (missing info / nonsense / hallucination danger), the model must respond:

{"status": "error", "message": "Missing value for field 'name'"}

YOLOQuery will turn that into an AIQueryLLMError (attached to an empty QuerySet unless raise_errors=True).


Supported Query Concepts

You Say LLM Might Output Django Filters
"authors named john" name iexact John name__iexact="John"
"authors from usa or canada" logic=or + country in [USA, Canada] `Q(country__iexact="USA") Q(country__iexact="Canada")`
"books published after 2020" published_date gt 2020-01-01 published_date__gt=date(2020,1,1)
"authors with books after 2020" books__published_date gt 2020-01-01 join across reverse M2M
"top 10 newest books" order_by=-published_date, limit=10 .order_by('-published_date')[:10]

Error Handling

YOLOQuery errs on the side of not doing something dumb:

qs = Author.objects.ai_query("authors where")  # incomplete!
if hasattr(qs, 'ai_error'):
    print("LLM said nope:", qs.ai_error)

Raise immediately:

Author.objects.ai_query("authors where", raise_errors=True)
# AIQueryLLMError: LLM could not translate query.

Testing (No API Calls)

from django_yoloquery import DummyLLM

DUMMY_RESPONSES = {
    "authors named John": {
        "status": "ok",
        "filters": [{"path": "name", "op": "iexact", "value": "John"}]
    },
    "name is": {
        "status": "error", "message": "Missing value for name"
    },
}

dummy = DummyLLM(DUMMY_RESPONSES)
qs = Author.objects.ai_query("authors named John", llm=dummy)
assert list(qs.values_list("name", flat=True)) == ["John"]

FAQ (Frequently Asked Questions No One Asked Yet)

Q: Does this belong in production? A: The library literally has YOLO in the name.

Q: Will it leak my schema to OpenAI? A: Yes, that’s how it works. Use stub schemas or anonymized field names if that’s a problem.

Q: Can I use Anthropic / local models? A: PRs welcome. Right now it’s OpenAI only; we rely on JSON Schema format.

Q: What if the model hallucinates? A: We validate every field + op; hallucinations become errors instead of DB hits. (We try, anyway.)

Q: Does it understand dates like "last quarter"? A: Depends on the model; we just validate output.


Requirements

  • Python 3.8+
  • Django 3.2+
  • openai>=1.0.0
  • OpenAI API key

License

MIT – see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_yoloquery-0.1.3.tar.gz (15.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_yoloquery-0.1.3-py3-none-any.whl (12.5 kB view details)

Uploaded Python 3

File details

Details for the file django_yoloquery-0.1.3.tar.gz.

File metadata

  • Download URL: django_yoloquery-0.1.3.tar.gz
  • Upload date:
  • Size: 15.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.1

File hashes

Hashes for django_yoloquery-0.1.3.tar.gz
Algorithm Hash digest
SHA256 450621b2bfab9baec8a5a9d13717ebbd2dd413dca765274c97bc8a30bccc520c
MD5 246d30ee8ecdd22c2af80dd27ab40f56
BLAKE2b-256 99d60d82e123c048aba23aa9159c6a07886fa605d1f8e0e404085adae816d5a0

See more details on using hashes here.

File details

Details for the file django_yoloquery-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for django_yoloquery-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 36a724049ed2b51ba572b150e860611c4900c16b6a70cb7db86eba0f5d8db049
MD5 b77d8f16006002faeb1e13c68e8cf89d
BLAKE2b-256 e15a57b2f7e5a0f461c835f1d74a7a38fbd28bf84bc521c6a296d6621f963c51

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page