[Bug]: response_format_json_object=True is silently dropped, so JSON mode never reaches the model
Maintainer thường phản hồi trong vòng 5 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 72/100
Hướng nghiên cứu
Bắt đầu từ packages/graphrag-llm/graphrag_llm/completion/lite_llm_completion.py, nơi _base_completion và _base_completion_async kiểm tra "response_format" not in new_args trước khi bật chế độ JSON. Khóa này luôn tồn tại với giá trị None, vì vậy điều kiện nên kiểm tra None thay thế. Sau đó xem QueryState.add_all_follow_ups và find_incomplete_actions trong graphrag/query/structured_search/drift_search/state.py, các hàm này nên bỏ qua các follow-up không phải chuỗi. Hoàn thành khi script tái hiện cho thấy {'type': 'json_object'} được truyền vào LiteLLM, tái hiện 2 không còn ném AttributeError và các unit test bao phủ cả hai trường hợp.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Do you need to file an issue?
- I have searched the existing issues and this bug is not already filed.
- My model is hosted on OpenAI or Azure. If not, please look at the "model providers" issue and don't file a new one here.
- I believe this is a legitimate bug, not just a question. If this is a question, please use the Discussions area.
Describe the bug
Note on the provider checkbox: we run open-weight models via vLLM, but this bug does not depend on the provider. The reproduction below uses model_provider="openai" and never contacts a model.
Several query paths request JSON mode with response_format_json_object=True: the DRIFT local search actions (drift_search/search.py#L97), the global search map step (global_search/search.py#L97, #L240) and rate_relevancy (#L62). The flag never takes effect: the request sent to the model contains no response_format.
Root cause (graphrag_llm/completion/lite_llm_completion.py):
completionandcompletion_asyncpopresponse_format(defaultNone) and always pass it on explicitly (#L158, #L197)._base_completionand_base_completion_asynconly enable JSON mode if the key is absent (#L262, #L288):if json_object and "response_format" not in new_args:
Since the key is always present with the value None, this branch is never taken. LiteLLM then receives response_format=None and drops it.
Consequences in DRIFT (silent, only warnings are logged):
- Without JSON mode, models often answer an action in plain prose.
try_parse_json_objectthen returns{}, and the action yields no answer and no follow-ups ("No answer found for query"). - Models also return non-strict JSON with single quotes. The repair in
try_parse_json_objectsplits follow-up queries at escaped apostrophes and at the comma before a year, and the year becomes an int. Example:'...SBF\'s political dealings were mentioned in the October 7, 2023 TechCrunch digest?'becomes["What specific details about SBF ", "s political dealings were mentioned in the October 7", 2023, "TechCrunch digest?'"]. QueryState.add_all_follow_upslogs a warning for non-string items but still adds them to the graph (state.py#L45-L53).find_incomplete_actionsthen raisesAttributeError: 'int' object has no attribute 'is_complete'(#L57), and the whole DRIFT query fails.
Observed impact (vLLM 0.30.0, default DRIFT settings, MultiHop-RAG corpus): 5 to 25 % of DRIFT actions were answered in plain prose depending on the model (Qwen3.8-27B 5 to 14 %, Mistral-Small-3.2-24B 25 %). With Qwen3.8-27B, 3 to 5 % of DRIFT queries failed with the AttributeError even after two retries.
Steps to reproduce
- JSON mode is dropped (no network access, no model needed):
import asyncio
import logging
import graphrag_llm.completion.lite_llm_completion as llc
from graphrag_llm.completion import create_completion
from graphrag_llm.config import ModelConfig
logging.getLogger("graphrag_llm").setLevel(logging.CRITICAL) # hide the logged RuntimeError below
captured = {}
async def fake_acompletion(**kwargs):
captured.update(kwargs)
raise RuntimeError("stop before any network call")
llc.litellm.acompletion = fake_acompletion
model = create_completion(
ModelConfig(model_provider="openai", model="gpt-4o-mini", api_key="not-used")
)
async def main():
try:
await model.completion_async(
messages=[{"role": "user", "content": "Answer in JSON."}],
response_format_json_object=True,
)
except RuntimeError:
pass
asyncio.run(main())
print("response_format passed to litellm:", captured.get("response_format"))
# Actual: None
# Expected: {'type': 'json_object'}
- A non-string follow-up crashes DRIFT:
from graphrag.query.structured_search.drift_search.action import DriftAction
from graphrag.query.structured_search.drift_search.state import QueryState
state = QueryState()
parent = DriftAction(query="parent question")
state.add_action(parent)
state.add_all_follow_ups(parent, ["a valid follow-up question", 2023])
state.find_incomplete_actions()
# AttributeError: 'int' object has no attribute 'is_complete'
Expected Behavior
When response_format_json_object=True is passed and no explicit response_format is given, LiteLLM receives response_format={"type": "json_object"}. A follow-up query that is not a string should be skipped instead of crashing the DRIFT search.
GraphRAG Config Used
# Excerpt of settings.yaml. All other settings are GraphRAG 3.1.0 defaults.
# The JSON-mode bug does not depend on this config: reproduction 1 runs without any settings file.
completion_models:
default_completion_model:
model_provider: hosted_vllm # bug also reproduced with model_provider: openai (reproduction 1)
model: Qwen/Qwen3.8-27B # also observed with mistralai/Mistral-Small-3.2-24B-Instruct-2506
api_base: ${VLLM_API_BASE}
api_key: ${GRAPHRAG_API_KEY}
call_args: # query time
temperature: 0
top_p: 1
max_tokens: 4000
retry:
type: exponential_backoff
max_retries: 2
embedding_models:
default_embedding_model:
model_provider: hosted_vllm
model: BAAI/bge-m3
api_base: ${VLLM_EMBED_API_BASE}
api_key: ${GRAPHRAG_API_KEY}
drift_search: # GraphRAG 3.1.0 defaults
completion_model_id: default_completion_model
embedding_model_id: default_embedding_model
n_depth: 3
drift_k_followups: 20
primer_folds: 5
concurrency: 32
Logs and screenshots
Reproduction 1 prints: response_format passed to litellm: None
Reproduction 2 raises: AttributeError: 'int' object has no attribute 'is_complete' (state.py, line 57)
Additional Information
- Versions: graphrag 3.1.0, graphrag-llm 3.1.0, litellm 1.86.2, Python 3.13. The same code is in v3.1.2, v3.2.0, v3.3.0 and on main (34b2b67).
- Suggested fix 1, in both
_base_completionand_base_completion_async:
if json_object and new_args.get("response_format") is None:
With this change, reproduction 1 prints{'type': 'json_object'}. - Suggested fix 2 (defensive): in
QueryState.add_all_follow_ups,continueafter the warning for non-string items. With fix 1 the trigger mostly disappears, butjson_objectmode does not constrain types, so a model can still return non-string items. - I am happy to open a PR with both changes and unit tests.
- Ngôn ngữ chính
- Python
- Star
- 36.6k
- Fork
- 3.9k
- Merge trung bình
- 4 ngày 11 giờ
- Pull request đã merge (30 ngày)
- 1
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của microsoft/graphrag
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
microsoft/graphrag#2626 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 5 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 95/100
Maintainer thường phản hồi trong vòng 5 ngày
-
[Bug]: JsonCache.get() crashes with unhandled AttributeError on non-dict or invalid envelope JSON payloadsCó thể làm lại được Pull request cho issue này đã bị đóng mà không được merge. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
microsoft/graphrag#2614 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 5 ngày
-
[Bug]: JSONLinesFileReader drops rows containing U+2028, U+2029 or U+0085 (uses str.splitlines)Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
microsoft/graphrag#2594 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 5 ngày
-
[Bug]: TokenChunker never terminates when chunking overlap >= size (no validation of size/overlap)Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
microsoft/graphrag#2593 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 5 ngày
Tất cả issue của microsoft/graphrag
Issue tương tự
-
bug
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 78/100
splunk/security_content#4418 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug / Enhancement]: Improve teleop_robot CLI with configurable timeout, robust input validation, and clean ROS shutdownCó thể đã có người làm @muskan-creates352 đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 3 ngày
-
bug(pipelines): shortcode stripping deletes text between a {{< >}} shortcode and the next {{% %}}Có thể đã có người làm @Ashborne-lab đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
kubeflow/docs-agent#293 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
Imbad0202/academic-research-skills#1093 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Input: placeholder drawn in the text colour when the empty Input is focused but not yet editedĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
pierreaubert/gpui-toolkit#114 ·
Maintainer thường phản hồi trong vòng 1 ngày