[Bug]: create_community_reports fails on strict/flat-schema guided-JSON backends (nested response_format)

Aperta
#2,571 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 5 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
65/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
json, python
Ambito
ai, backend

Direzione di ricerca

Look at the CommunityReportsExtractor in the codebase, likely in a file like community_reports.py or extractors/. The bug is in how response_format is passed to LLMCompletion.completion_async. The fix involves removing the nested Pydantic model from the response_format, parsing the JSON response manually, and validating it with CommunityReportResponse. Check the existing tests in tests/verbs/test_create_community_reports.py to understand the expected behavior and ensure the fix doesn't break them.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Do you need to file an issue?
  • I have searched the existing issues and this bug is not already filed.
  • My model is not hosted on OpenAI or Azure — see note below on why this isn't a "model providers" question.
  • I believe this is a legitimate bug, not just a question.

Note on the "model providers" checkbox: I'm reproducing this against a
Databricks AI Gateway (serving an open-weights model), but the root cause
is not provider-specific — it's how CommunityReportsExtractor builds its
response_format. Any backend that enforces strict/flat JSON Schema
guided decoding (vLLM guided decoding, outlines, lm-format-enforcer
servers, etc.) will hit the exact same failure, because the bug is in how
the Pydantic schema for CommunityReportResponse gets generated on the
client side, not in anything provider-specific.

Describe the bug

CommunityReportsExtractor.__call__ passes
response_format=CommunityReportResponse to LLMCompletion.completion_async,
where CommunityReportResponse.findings is typed as list[FindingModel] —
a nested Pydantic BaseModel.

Pydantic's model_json_schema() (and litellm's type_to_response_format_param,
which builds the actual {"type": "json_schema", ...} wire payload from it)
always factors a nested BaseModel out into a top-level $defs entry
referenced via $ref. There is no built-in option to force full inlining.

A number of OpenAI-"strict"-mode-compatible guided-JSON backends only
implement the flat subset of JSON Schema and reject any schema containing
$defs/$ref outright. Concretely, I hit this against a Databricks AI
Gateway serving an open-weights model (gpt-oss-20b):

litellm.BadRequestError: DatabricksException - {"error_code":"BAD_REQUEST","message":"Invalid JSON schema - /$defs/FindingModel\n"}

The same class of guided-decoding backend (vLLM's guided decoding,
outlines, lm-format-enforcer-based servers) is known to have the same
restriction, so this isn't Databricks-specific.

Impact: every single call to create_community_reports fails with this
error on any such backend. summarize_communities catches the exception
per-community (No report found for community: N), so the workflow doesn't
crash immediately and indexing keeps going with a misleading Pipeline complete — the run only reports the failure at the very end, when
finalize_community_reports tries to pandas.merge the (empty) reports
frame on a community column that was never produced, and raises
KeyError: 'community'.

Suggested fix (already implemented and validated on my side, see
"Logs and screenshots" below): since the prompt already asks for the JSON
shape in prose, stop relying on server-side structured-output enforcement
for this one call and instead parse + validate the response text on the
client — drop response_format=CommunityReportResponse from the
completion_async(...) call, add a small _parse_json_response(content: str) -> dict helper that json.loadss the raw text (tolerating a wrapping
```json fence and leading/trailing prose via a fallback slice between
the first { and last }), and construct
CommunityReportResponse(**_parse_json_response(response.content))
directly. No public API changes: CommunityReportsResult,
CommunityReportResponse, and FindingModel are unchanged.

Pull request creation on this repo currently appears restricted to
collaborators, so I can't open a PR directly — happy to submit one (or
paste the diff here) if a maintainer can enable that, or if someone with
write access wants to apply it.

Steps to reproduce
  1. Configure graphrag to use a completion backend that enforces strict/flat
    JSON Schema guided decoding (e.g. a Databricks AI Gateway serving an
    open-weights model, or a self-hosted vLLM server with guided decoding).
  2. Run graphrag index on any corpus that reaches the create_community_reports
    workflow step.
  3. Observe every community report call fail with something like:
    litellm.BadRequestError: ... Invalid JSON schema - /$defs/FindingModel
  4. The run still ends with a misleading Pipeline complete; the real
    failure only surfaces as KeyError: 'community' from
    finalize_community_reports.

Minimal repro isolating the variable (no graphrag needed):

from pydantic import BaseModel
import litellm

class Finding(BaseModel):
    summary: str
    explanation: str

class FlatReport(BaseModel):
    title: str
    summary: str
    rating: float

class NestedReport(BaseModel):
    title: str
    summary: str
    findings: list[Finding]
    rating: float

litellm.completion(..., response_format=FlatReport)    # succeeds
litellm.completion(..., response_format=NestedReport)   # BadRequestError: Invalid JSON schema - /$defs/Finding
Expected Behavior

create_community_reports should succeed on any OpenAI-compatible backend
whose completion model can follow the prompt's JSON instructions, regardless
of whether that backend supports server-side schemas containing $defs/$ref.

GraphRAG Config Used
# Not config-specific -- reproducible with any completion_models backend
# that enforces strict/flat JSON Schema guided decoding. In my case:
completion_models:
  default_completion_model:
    type: litellm
    model_provider: databricks
    model: databricks/gpt-oss-20b  # served via a Databricks AI Gateway
Logs and screenshots

Before the fix, against a real ~1.1MB / 32-document corpus:

litellm.BadRequestError: DatabricksException - {"error_code":"BAD_REQUEST","message":"Invalid JSON schema - /$defs/FindingModel\n"}

0 / 357 communities got a report (100% failure); the run ends in a
misleading "Pipeline complete", with the real failure only surfacing as:

KeyError: 'community'

from finalize_community_reports's pandas.merge on the (empty) reports
frame.

After the fix described above: 350 / 357 communities got a report (98%);
the remaining ~2% failed for unrelated, expected reasons (a transient rate
limit and one case of genuinely malformed JSON from the model), not the
schema bug. tests/verbs/test_create_community_reports.py (mocked
completion path) also still passes after the change.

Additional Information
  • GraphRAG Version: current main (post uv-workspace monorepo restructure)
  • Operating System: Linux (Databricks Gateway backend), reproduced logic
    verified on Windows too
  • Python Version: 3.12
  • Related Issues:
Lingua principale
Python
Stelle
36.6k
Fork
3.9k
Merge medio
4g 11h
PR unite (30g)
1

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di microsoft/graphrag

Tutte le issue di microsoft/graphrag

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.