Skip to content

fix(deriver): document explicit observation JSON shape#901

Open
PraveenKumarSridhar wants to merge 1 commit into
plastic-labs:mainfrom
PraveenKumarSridhar:fix/893-deriver-explicit-json-shape
Open

fix(deriver): document explicit observation JSON shape#901
PraveenKumarSridhar wants to merge 1 commit into
plastic-labs:mainfrom
PraveenKumarSridhar:fix/893-deriver-explicit-json-shape

Conversation

@PraveenKumarSridhar

@PraveenKumarSridhar PraveenKumarSridhar commented Jul 12, 2026

Copy link
Copy Markdown

Summary

  • Clarify the deriver prompt's expected PromptRepresentation.explicit JSON shape for json_object structured-output fallback.
  • Update the PromptRepresentation schema description so OpenAI-compatible providers see object-shaped examples, not bare string examples.
  • Add regression coverage for the prompt, the schema hint, and the OpenAI json_object schema-injection path.

Closes #893.

Why

PromptRepresentation.explicit expects a list of objects with a content field. In json_object mode, providers rely on prompt/schema text to infer the shape, so examples that imply bare strings can lead to validation failures and silently empty observations.

Testing

  • .venv/bin/pytest tests/deriver/test_prompts.py tests/llm/test_backends/test_openai.py -q → 55 passed
  • .venv/bin/ruff check src/deriver/prompts.py src/utils/representation.py tests/deriver/test_prompts.py tests/llm/test_backends/test_openai.py → All checks passed
  • .venv/bin/basedpyright src/deriver/prompts.py src/utils/representation.py tests/deriver/test_prompts.py tests/llm/test_backends/test_openai.py → 0 errors

Broader deriver queue tests were attempted, but local Postgres auth setup rejected the test DB connection, so I kept verification to the prompt and OpenAI backend tests touched by this fix.

Developed with AI assistance; reproduced, tested, and reviewed locally before submission.

Summary by CodeRabbit

  • Improvements

    • Clarified structured AI output requirements so explicit observations are returned in the expected JSON object/array shape with a content field.
    • Updated schema/prompt examples to match the enforced JSON format.
  • Bug Fixes

    • Improved validation to reject incorrectly formatted explicit observations (e.g., plain string forms).
  • Tests

    • Added prompt and JSON-shape tests, including schema example checks.
    • Added OpenAI backend coverage for structured json_object responses using the prompt representation.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0f11ea02-9fef-4d25-b119-1b39fe44fbe1

📥 Commits

Reviewing files that changed from the base of the PR and between 6b45815 and 4112f94.

📒 Files selected for processing (4)
  • src/deriver/prompts.py
  • src/utils/representation.py
  • tests/deriver/test_prompts.py
  • tests/llm/test_backends/test_openai.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/deriver/prompts.py
  • tests/llm/test_backends/test_openai.py
  • src/utils/representation.py

Walkthrough

The deriver prompt and representation schema now require explicit observations as objects with content fields. Tests cover prompt wording, Pydantic validation, schema descriptions, and OpenAI json_object parsing.

Changes

Explicit observation shape

Layer / File(s) Summary
Prompt and representation contract
src/deriver/prompts.py, src/utils/representation.py
The prompt and schema example now describe explicit as an array of objects containing content strings.
Shape validation and backend coverage
tests/deriver/test_prompts.py, tests/llm/test_backends/test_openai.py
Tests verify valid and invalid JSON shapes, generated schema descriptions, and parsing through the OpenAI json_object mode.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: adavyas, rajat-ahuja1997

Poem

A bunny found facts in a JSON array,
With content tucked neatly there.
No more bare strings bouncing free,
The schema now matches perfectly.
Hop, parse, and validate with glee! 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: documenting the explicit observation JSON shape.
Linked Issues check ✅ Passed The prompt, schema example, and regression tests all address the explicit-field shape mismatch in #893.
Out of Scope Changes check ✅ Passed The extra test fixture adjustments support the new regression coverage and stay within the issue scope.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@PraveenKumarSridhar
PraveenKumarSridhar marked this pull request as ready for review July 12, 2026 21:12

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/utils/representation.py`:
- Line 117: Reformat the description argument in the relevant configuration or
declaration so the long string is split across adjacent concatenated string
literals, keeping the exact text unchanged and each Python source line within
the 88-character limit.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ac18d8b-e8b7-43e6-8d1d-fd09243e319a

📥 Commits

Reviewing files that changed from the base of the PR and between 73453f8 and 6b45815.

📒 Files selected for processing (4)
  • src/deriver/prompts.py
  • src/utils/representation.py
  • tests/deriver/test_prompts.py
  • tests/llm/test_backends/test_openai.py

Comment thread src/utils/representation.py Outdated

explicit: list[ExplicitObservationBase] = Field(
description="Facts LITERALLY stated by the user - direct quotes or clear paraphrases only, no interpretation or inference. Example: ['The user is 25 years old', 'The user has a dog named Rover']",
description='Facts LITERALLY stated by the user - direct quotes or clear paraphrases only, no interpretation or inference. Example: [{"content": "The user is 25 years old"}, {"content": "The user has a dog named Rover"}]',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Line 117 exceeds the 88-character limit.

As per coding guidelines, Python lines should be kept within 88 characters to match Black-compatible formatting. The description string on this line is well over that limit. Consider splitting the string across multiple concatenated lines.

♻️ Proposed refactor
-    explicit: list[ExplicitObservationBase] = Field(
-        description='Facts LITERALLY stated by the user - direct quotes or clear paraphrases only, no interpretation or inference. Example: [{"content": "The user is 25 years old"}, {"content": "The user has a dog named Rover"}]',
+    explicit: list[ExplicitObservationBase] = Field(
+        description=(
+            "Facts LITERALLY stated by the user - direct quotes or clear "
+            "paraphrases only, no interpretation or inference. Example: "
+            '[{"content": "The user is 25 years old"}, '
+            '{"content": "The user has a dog named Rover"}]'
+        ),
         default_factory=list,
     )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
description='Facts LITERALLY stated by the user - direct quotes or clear paraphrases only, no interpretation or inference. Example: [{"content": "The user is 25 years old"}, {"content": "The user has a dog named Rover"}]',
explicit: list[ExplicitObservationBase] = Field(
description=(
"Facts LITERALLY stated by the user - direct quotes or clear "
"paraphrases only, no interpretation or inference. Example: "
'[{"content": "The user is 25 years old"}, '
'{"content": "The user has a dog named Rover"}]'
),
default_factory=list,
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils/representation.py` at line 117, Reformat the description argument
in the relevant configuration or declaration so the long string is split across
adjacent concatenated string literals, keeping the exact text unchanged and each
Python source line within the 88-character limit.

Source: Coding guidelines

@PraveenKumarSridhar
PraveenKumarSridhar force-pushed the fix/893-deriver-explicit-json-shape branch from 6b45815 to 4112f94 Compare July 12, 2026 21:17
@PraveenKumarSridhar

Copy link
Copy Markdown
Author

Fixed in 4112f94 — split the description string across adjacent concatenated literals in src/utils/representation.py:117 to satisfy the 88-char line limit. Schema text unchanged; tests still 55/55. Thanks for the catch, CodeRabbit!

@PraveenKumarSridhar

Copy link
Copy Markdown
Author

Hi maintainers — I noticed that #893 was closed after #907 added schema injection for json_object mode and the reporter confirmed that approach works on current main.

The prompt and schema-description clarifications in this PR are not currently in main, but they may now be redundant given #907. Would you still find this PR useful as additional hardening and regression coverage, or should I close it as superseded by #907?

I am happy to rebase and update it if you would still like these changes merged.

@karaokedjodua

Copy link
Copy Markdown

Finn-loop review of 4112f94

CI: not configured — no required checks reported on this branch
Mergeability: clean (mergeable: MERGEABLE, but mergeStateStatus: BLOCKED — stale branch protection rule)

Review

Summary: Updates the deriver prompt and PromptRepresentation schema to use object-shaped examples ({"content": "..."}) instead of bare strings, preventing json_object fallback failures. Adds regression tests for the prompt, schema, and OpenAI json_object path.

1. Must fix before merge

  • [CI] No required CI checks are configured on this branch. gh pr checks --required returns "no required checks reported" — a human must set up branch protection or confirm this is acceptable. Additionally, mergeStateStatus: BLOCKED with mergeable: MERGEABLE indicates a stale branch-protection rule referencing a check that no longer exists or doesn't match — an admin must update or remove the stale rule.

2. Should fix soon

None.

3. Safe to merge

Yes on code merits — the changes are minimal, exactly scoped to the contract, and well-tested. The stale branch-protection rule and missing CI are repo-configuration issues, not code defects.

Note: No formal issue was linked (Closes #893 references a GitHub issue, not a Paperclip KAR-NNN). Reviewed against the PR body as contract.

Labels that should be applied: loop-approved, needs-human-review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deriver prompt instructs LLM to return wrong JSON shape for explicit, causing zero observations with OpenAI-compatible providers (DeepSeek, vLLM)

2 participants