Skip to content

LLM CALL: save bypassed entry in db as well#826

Merged
AkhileshNegi merged 8 commits into
mainfrom
bug/llm_call_entry
May 14, 2026
Merged

LLM CALL: save bypassed entry in db as well#826
AkhileshNegi merged 8 commits into
mainfrom
bug/llm_call_entry

Conversation

@nishika26
Copy link
Copy Markdown
Collaborator

@nishika26 nishika26 commented May 11, 2026

Summary

Target issue is #828

Notes

Release Notes

  • New Features

    • Added database tracking for rephrase guardrail operations, storing original queries and safe text responses for audit and monitoring purposes.
  • Tests

    • Added test coverage for guardrail rephrase functionality and database persistence.

Review Change Stack

Summary by CodeRabbit

  • New Features

    • Persist guardrail rephrase responses alongside the original user input, storing a zero-token safe response and returning a reference ID when saved (returns null on failure).
    • Improved serialization of LLM configuration for more consistent storage.
  • Reliability

    • Increased timeout when calling guardrails endpoint to reduce spurious timeouts.
  • Tests

    • Added tests verifying persistence of original input, safe rephrase content, zero-token usage, and error-handling when saving fails.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6a5d887e-ee10-494d-927f-80e7e1d3846e

📥 Commits

Reviewing files that changed from the base of the PR and between c80af4b and f1a997c.

📒 Files selected for processing (3)
  • backend/app/crud/llm.py
  • backend/app/services/llm/guardrails.py
  • backend/app/tests/services/llm/test_guardrails.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/app/services/llm/guardrails.py
  • backend/app/crud/llm.py

📝 Walkthrough

Walkthrough

Persists guardrail rephrase calls: changes config serialization to JSON mode, adds save_rephrase_guardrail_call to persist rephrase responses, integrates persistence into execute_llm_call (restores original input), and adds tests for success and failure paths.

Changes

Guardrail Rephrase Persistence

Layer / File(s) Summary
Config serialization format update
backend/app/crud/llm.py
Database persistence of LLM call configs now uses model_dump(mode="json") for non-stored-config paths; module imports updated for new types.
Guardrail persistence infrastructure
backend/app/crud/llm.py, backend/app/services/llm/guardrails.py
Adds save_rephrase_guardrail_call which creates an LlmCall record, records a zero-token text response via update_llm_call_response, returns the saved call id or None on error; increased guardrails HTTP client timeout.
Job execution integration
backend/app/services/llm/jobs.py
execute_llm_call captures original TextInput value, restores it when a guardrail_direct_response is returned, calls save_rephrase_guardrail_call, and returns a BlockResult including llm_call_id and usage/metadata.
Persistence validation tests
backend/app/tests/services/llm/test_jobs.py, backend/app/tests/services/llm/test_guardrails.py
New tests assert rephrase guardrail persistence of original input and safe text, zero token usage, forwarding of optional fields, and failure handling when CRUD helpers raise.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • AkhileshNegi
  • vprashrex
  • Prajna1999

Poem

🐰 I dug through code with nimble paws,
Found guardrail words and changed their cause.
Original input kept safe in store,
Rephrased words saved and tokens floor.
A little hop — persistence galore! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.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 refers to a real aspect of the change—database persistence of rephrase guardrail calls—but understates the scope by using the term 'bypassed entry' which is narrower than the actual implementation of saving both original input and guardrail-safe responses.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bug/llm_call_entry

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 and usage tips.

@nishika26 nishika26 force-pushed the bug/llm_call_entry branch from bb74426 to 4663ffb Compare May 12, 2026 04:28
@nishika26 nishika26 assigned nishika26 and unassigned nishika26 May 12, 2026
@nishika26 nishika26 added ready-for-review bug Something isn't working labels May 12, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
backend/app/tests/services/llm/test_jobs.py (1)

1201-1217: ⚡ Quick win

Use a fixture factory instead of an inline request payload.

Line 1201 builds a full request dict inline; please route this through a factory-style fixture/helper for consistency with test-data construction standards.

As per coding guidelines, backend/app/tests/**/*.py: Use factory pattern for test fixtures in backend/app/tests/.

🤖 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 `@backend/app/tests/services/llm/test_jobs.py` around lines 1201 - 1217,
Replace the inline request_data dict in test_jobs.py with a factory-style
fixture: extract the payload construction (the "query" and "config" with "blob"
/ "completion" / "params" and "input_guardrails" using VALIDATOR_CONFIG_ID_1)
into a test factory helper (e.g., request_payload_factory or
build_request_payload) in the test fixtures module and then call that factory
from the test before invoking _execute_job(job_for_execution, db, payload);
ensure the factory accepts overrides for fields like model and validator IDs so
other tests can reuse it and keep the same variable names (request_data,
job_for_execution, VALIDATOR_CONFIG_ID_1) to minimize changes.
🤖 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 `@backend/app/tests/services/llm/test_jobs.py`:
- Around line 1177-1179: The test method
test_guardrails_rephrase_saves_original_input_and_safe_text_in_db is missing
type hints for its parameters and return value; update its signature to add
appropriate typing for db, job_env, and job_for_execution (e.g., use the
repository's existing fixture types or typing.Any/Fixture types used elsewhere)
and annotate the return type as -> None so the function signature follows the
project's typing rules.

---

Nitpick comments:
In `@backend/app/tests/services/llm/test_jobs.py`:
- Around line 1201-1217: Replace the inline request_data dict in test_jobs.py
with a factory-style fixture: extract the payload construction (the "query" and
"config" with "blob" / "completion" / "params" and "input_guardrails" using
VALIDATOR_CONFIG_ID_1) into a test factory helper (e.g., request_payload_factory
or build_request_payload) in the test fixtures module and then call that factory
from the test before invoking _execute_job(job_for_execution, db, payload);
ensure the factory accepts overrides for fields like model and validator IDs so
other tests can reuse it and keep the same variable names (request_data,
job_for_execution, VALIDATOR_CONFIG_ID_1) to minimize changes.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e572c28d-2925-4ec9-ab3c-c034449b9c71

📥 Commits

Reviewing files that changed from the base of the PR and between e8d87ff and b84617a.

📒 Files selected for processing (4)
  • backend/app/crud/llm.py
  • backend/app/services/llm/guardrails.py
  • backend/app/services/llm/jobs.py
  • backend/app/tests/services/llm/test_jobs.py

Comment thread backend/app/tests/services/llm/test_jobs.py
@codecov
Copy link
Copy Markdown

codecov Bot commented May 12, 2026

Codecov Report

❌ Patch coverage is 97.95918% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
backend/app/crud/llm.py 88.23% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

Comment thread backend/app/services/llm/guardrails.py Outdated
Comment on lines +230 to +234
usage={
"input_tokens": 0,
"output_tokens": 0,
"total_tokens": 0,
},
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why we are hardcoding this?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

because llm is not being hit so no token numbers will be calculated, we get this token number from when it goes through llm

Comment thread backend/app/services/llm/guardrails.py Outdated
Comment on lines +223 to +227
content={
"type": "text",
"content": {
"format": "text",
"value": guardrail_direct_response,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we should be able to identify in some way that this response was from guardrail and actual LLM Call didn't happen otherwise with the format it might get confusing and users may end up fixing things in LLM end

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

maybe later on you can add a "source" key inside content where you can put guardrail in teh case of guardrail and llm in the case of llm

Comment thread backend/app/services/llm/guardrails.py Outdated
Comment thread backend/app/services/llm/guardrails.py Outdated
input_guardrails=config_blob.input_guardrails,
output_guardrails=config_blob.output_guardrails,
)
rephrase_llm_call = create_llm_call(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we use this directly instead of creating with same four fields again

rephrase_llm_call = create_llm_call(
      session,
      request=rephrase_call_request,
      job_id=job_id,
      project_id=project_id,
      organization_id=organization_id,
      resolved_config=config_blob,   # ← was rephrase_resolved_config
      original_provider=str(config_blob.completion.provider),
      chain_id=chain_id,
  )

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

took care of this as well

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/app/tests/services/llm/test_guardrails.py (1)

285-375: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add type hints to all newly added test signatures.

Line 285 and Lines 293-375 introduce new methods with untyped parameters (job, **overrides) and incomplete signature typing coverage. Please annotate all parameters and return types in this new test class.

As per coding guidelines, **/*.py: Always add type hints to all function parameters and return values in Python code.

🤖 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 `@backend/app/tests/services/llm/test_guardrails.py` around lines 285 - 375,
The tests add untyped functions — annotate the fixture and all test/signature
params and return types: update the job fixture signature to def job(self, db:
Session) -> Job (or the project Job model type), annotate _call as def
_call(self, db: Session, job: Job, **overrides: Any) -> Optional[UUID] (or UUID
if always returning one), and add explicit return types to each test method
(e.g., -> None) and typed local vars where needed; import typing symbols (Any,
Optional, Dict) and the UUID/Job types used so create_llm_call,
update_llm_call_response, and each test (test_success_returns_uuid,
test_success_saves_original_input_and_job_id,
test_success_saves_safe_text_as_content, test_success_saves_zero_usage,
test_create_llm_call_error_returns_none,
test_update_llm_call_response_error_returns_none,
test_chain_id_forwarded_to_create_llm_call,
test_request_metadata_forwarded_to_llm_call_request) have full parameter and
return annotations.
🤖 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 `@backend/app/tests/services/llm/test_guardrails.py`:
- Around line 286-291: The job fixture currently uses JobCrud.create (creating a
Job with JobType.LLM_API and trace_id="rephrase-test")—replace that direct CRUD
usage with the project’s test factory pattern: call the existing job factory
fixture (e.g., job_factory or create_job_factory) to build/persist a Job with
the same attributes (job_type=JobType.LLM_API, trace_id="rephrase-test"), commit
if the factory requires it, and return the created job; remove JobCrud and
direct DB manipulation and rely on the shared factory to ensure consistency with
other tests.

---

Outside diff comments:
In `@backend/app/tests/services/llm/test_guardrails.py`:
- Around line 285-375: The tests add untyped functions — annotate the fixture
and all test/signature params and return types: update the job fixture signature
to def job(self, db: Session) -> Job (or the project Job model type), annotate
_call as def _call(self, db: Session, job: Job, **overrides: Any) ->
Optional[UUID] (or UUID if always returning one), and add explicit return types
to each test method (e.g., -> None) and typed local vars where needed; import
typing symbols (Any, Optional, Dict) and the UUID/Job types used so
create_llm_call, update_llm_call_response, and each test
(test_success_returns_uuid, test_success_saves_original_input_and_job_id,
test_success_saves_safe_text_as_content, test_success_saves_zero_usage,
test_create_llm_call_error_returns_none,
test_update_llm_call_response_error_returns_none,
test_chain_id_forwarded_to_create_llm_call,
test_request_metadata_forwarded_to_llm_call_request) have full parameter and
return annotations.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 71bef9e5-160c-47ce-b490-2584c0d451d0

📥 Commits

Reviewing files that changed from the base of the PR and between b84617a and d0d07b2.

📒 Files selected for processing (3)
  • backend/app/crud/llm.py
  • backend/app/services/llm/jobs.py
  • backend/app/tests/services/llm/test_guardrails.py

Comment thread backend/app/tests/services/llm/test_guardrails.py Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 `@backend/app/crud/llm.py`:
- Around line 271-305: The create/update sequence for the rephrase LLM call must
be made atomic to avoid partial persistence: ensure the creation and the
subsequent update happen inside a single DB transaction (or use new
non-committing helpers) so either both writes succeed or both are rolled back.
Concretely, wrap the calls to create_llm_call and update_llm_call_response (the
block that constructs LLMCallRequest and calls
create_llm_call/rephrase_llm_call.id then update_llm_call_response) in a single
transaction scope, or implement and call internal variants like
create_llm_call_no_commit and update_llm_call_response_no_commit and then commit
once after both succeed; if any error occurs, rollback and return None.
- Around line 290-291: The code is incorrectly storing job_id in the
provider_response_id field; instead keep provider_response_id reserved for the
actual provider response identifier (or None) and move job_id into a dedicated
metadata field (e.g., add metadata={"job_id": str(job_id)} or include "job_id"
inside the existing content/metadata dict). Update the call that currently sets
provider_response_id=str(job_id) to set provider_response_id=None (or the real
provider id variable) and add the job_id to content or metadata so traceability
is preserved without overloading provider_response_id.

In `@backend/app/tests/services/llm/test_guardrails.py`:
- Around line 293-308: The helper _call lacks full type hints: annotate its
parameters and return type (e.g., def _call(db: Session, job: Job, **overrides:
Any) -> GuardrailCall) and import any needed types (Session, Job model,
GuardrailCall/return type from save_rephrase_guardrail_call, and Any); likewise
add explicit return/type annotations to the job fixture and to all new test
function parameters (e.g., job: Job) in the 310-375 range so every function
parameter and return value uses Python 3.11+ type hints consistent with
QueryParams, save_rephrase_guardrail_call, and the symbols
_CONFIG/_CONFIG_BLOB/_SAFE_TEXT used in the helper.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 31b92230-61b7-46a1-8660-89bfe1d4ae08

📥 Commits

Reviewing files that changed from the base of the PR and between d0d07b2 and c80af4b.

📒 Files selected for processing (4)
  • backend/app/crud/llm.py
  • backend/app/services/llm/guardrails.py
  • backend/app/services/llm/jobs.py
  • backend/app/tests/services/llm/test_guardrails.py
✅ Files skipped from review due to trivial changes (1)
  • backend/app/services/llm/guardrails.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/app/services/llm/jobs.py

Comment thread backend/app/crud/llm.py
Comment thread backend/app/crud/llm.py Outdated
Comment thread backend/app/tests/services/llm/test_guardrails.py Outdated
@AkhileshNegi AkhileshNegi merged commit c336ed4 into main May 14, 2026
3 checks passed
@AkhileshNegi AkhileshNegi deleted the bug/llm_call_entry branch May 14, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working ready-for-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants