-
Notifications
You must be signed in to change notification settings - Fork 7
Integrate Config Management with Unified Api #447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds a typed ConfigBlob and updates LLMCallConfig to support either a stored config (id+version) or an ad‑hoc blob; introduces resolve_config_blob and adjusts execute_job (signature and flow) to resolve and use the blob for provider selection; models, CRUD, and tests updated to the nested completion shape. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client/API
participant Job as execute_job
participant ConfigCrud as ConfigVersionCrud
participant Provider as LLM Provider
Note over Job,ConfigCrud: Resolve stored vs ad-hoc config into a ConfigBlob
Client->>Job: submit LLMCallRequest (LLMCallConfig)
Job->>Job: validate_config_logic(config)
alt stored config (is_stored_config)
Job->>ConfigCrud: fetch by id+version
ConfigCrud-->>Job: ConfigVersion / error
Job->>Job: parse ConfigVersion.config_blob -> ConfigBlob
alt parse success
Job->>Provider: init(provider=config_blob.completion.provider)
Job->>Provider: execute(completion=config_blob.completion, task_instance)
else fetch/parse failure
Job-->>Client: emit failure callback (resolve/parse error)
end
else ad-hoc blob
Job->>Provider: init(provider=config.blob.completion.provider)
Job->>Provider: execute(completion=config.blob.completion, task_instance)
end
Provider-->>Job: result
Job-->>Client: success/failure callback
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this 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/models/config/config.py (1)
67-71: Remove or replace the ineffective validator check on ConfigBlob.The field_validator runs after Pydantic's internal validation, receiving a ConfigBlob instance. Since Pydantic models do not implement bool by default, model instances are always truthy. The check
if not valuewill never evaluate to True for a valid ConfigBlob object—it's dead code. The actual validation relies on ConfigBlob's requiredcompletionfield (CompletionConfig); invalid input dicts fail earlier during Pydantic validation, never reaching this validator. Either remove the validator or replace it with an explicit check likeif not value.completionif additional validation is needed.
🧹 Nitpick comments (5)
backend/app/services/llm/jobs.py (1)
122-122: Unused parametertask_instance.The
task_instanceparameter is added to the function signature but is not used anywhere in the function body. If this parameter is required by the Celery task framework or for future use, consider adding a comment explaining its purpose. Otherwise, consider removing it or prefixing with an underscore (_task_instance) to indicate it's intentionally unused.backend/app/models/config/version.py (1)
11-69: ConfigBlob-on-create design looks sound; consider typing the validatorUsing
ConfigBlobonly onConfigVersionCreatewhile keeping the stored/public models ondict[str, Any]is a clean separation of validated input vs JSONB storage and matches the inline comment here. The existingvalidate_blob_not_emptyvalidator still runs on both dicts andConfigBlobinstances, so behavior is preserved.For a small clarity win and to match the “use type hints” guideline, you could add annotations to
validate_blob_not_empty(e.g.cls: type["ConfigVersionBase"],value: dict[str, Any] | ConfigBlob, and an explicit return type), without changing logic.As per coding guidelines, ...
backend/app/tests/api/routes/configs/test_version.py (1)
29-36: ConfigBlob-shaped payloads look correct; consider DRYing and normalizing importsThe updated
config_blobJSON bodies in these tests now follow theConfigBlob/CompletionConfigstructure (completion → provider/params), and the empty-blob case still correctly yields a 422 via validation, so behavior is consistent with the new model.Two small refinements you might consider:
- Move the
from app.models.llm.request import ConfigBlob, CompletionConfigimport intest_get_version_by_numberup to the module top to keep import style uniform.- The repeated literal
config_blobpayloads could be produced by a small factory/fixture (e.g.make_config_blob_payload(model=..., **overrides)) so schema or default changes only need to be updated in one place.Based on learnings, centralizing test payload construction via factories/fixtures improves maintainability.
Also applies to: 91-96, 121-127, 154-159, 301-312, 451-456
backend/app/tests/utils/test_data.py (1)
3-24: Typed ConfigBlob integration in test helpers looks good; consider sharing the default blobUpdating
create_test_config/create_test_versionto acceptConfigBlob | Noneand constructing a defaultConfigBlob(CompletionConfig(...))when missing brings these helpers in line with the new config model and avoids leaking untyped dicts into call sites. That’s a solid improvement.If these defaults evolve, there’s a bit of duplication between the two
ConfigBlobconstructions (same provider and almost-identical params). A small factory (e.g.def make_default_config_blob(...) -> ConfigBlob) or fixture both helpers call would keep them perfectly in sync.Based on learnings, centralizing shared test objects via factories/fixtures reduces future maintenance.
Also applies to: 239-269, 283-305
backend/app/tests/crud/config/test_version.py (1)
6-27: Good use of a shared ConfigBlob fixture; minor consistency and type-hint nitsThe
example_config_blobfixture and its reuse across these CRUD tests nicely centralize the configuration shape and align the tests with theConfigBlob/CompletionConfigmodel. The checks thatfetched_version.config_blob == example_config_blob.model_dump()give a clear contract that the CRUD layer stores raw JSON, not model instances.Two optional cleanups:
- In
test_create_versionyou currentlymodel_dump()the fixture and pass that dict intoConfigVersionCreate, whereas other tests pass theConfigBlobdirectly. For consistency (and to avoid an extra parse/serialize round), you could passexample_config_blobintoConfigVersionCreateeverywhere and only usemodel_dump()for expected-value assertions.- Adding a return type annotation to the
example_config_blobfixture (def example_config_blob() -> ConfigBlob) would keep type hints complete in this module.Based on learnings, shared fixtures plus consistent usage patterns make the tests easier to evolve.
Also applies to: 29-49, 52-80, 98-120, 376-400
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
backend/app/crud/config/config.py(1 hunks)backend/app/crud/config/version.py(1 hunks)backend/app/models/__init__.py(1 hunks)backend/app/models/config/config.py(2 hunks)backend/app/models/config/version.py(2 hunks)backend/app/models/llm/__init__.py(1 hunks)backend/app/services/llm/jobs.py(3 hunks)backend/app/tests/api/routes/configs/test_config.py(3 hunks)backend/app/tests/api/routes/configs/test_version.py(6 hunks)backend/app/tests/crud/config/test_config.py(5 hunks)backend/app/tests/crud/config/test_version.py(9 hunks)backend/app/tests/utils/test_data.py(6 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Use type hints in Python code (Python 3.11+ project)
Files:
backend/app/crud/config/config.pybackend/app/tests/api/routes/configs/test_config.pybackend/app/models/config/config.pybackend/app/crud/config/version.pybackend/app/models/config/version.pybackend/app/tests/api/routes/configs/test_version.pybackend/app/models/llm/__init__.pybackend/app/services/llm/jobs.pybackend/app/tests/crud/config/test_config.pybackend/app/models/__init__.pybackend/app/tests/crud/config/test_version.pybackend/app/tests/utils/test_data.py
backend/app/crud/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Implement database access operations in backend/app/crud/
Files:
backend/app/crud/config/config.pybackend/app/crud/config/version.py
backend/app/models/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Define SQLModel entities (database tables and domain objects) in backend/app/models/
Files:
backend/app/models/config/config.pybackend/app/models/config/version.pybackend/app/models/llm/__init__.pybackend/app/models/__init__.py
backend/app/services/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Implement business logic services under backend/app/services/
Files:
backend/app/services/llm/jobs.py
🧠 Learnings (1)
📚 Learning: 2025-10-08T12:05:01.317Z
Learnt from: CR
Repo: ProjectTech4DevAI/ai-platform PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-08T12:05:01.317Z
Learning: Applies to app/tests/**/*.py : Use the factory pattern for test fixtures
Applied to files:
backend/app/tests/crud/config/test_config.pybackend/app/tests/crud/config/test_version.py
🧬 Code graph analysis (7)
backend/app/models/config/config.py (2)
backend/app/core/util.py (1)
now(13-14)backend/app/models/llm/request.py (1)
ConfigBlob(61-67)
backend/app/models/config/version.py (1)
backend/app/models/llm/request.py (1)
ConfigBlob(61-67)
backend/app/tests/api/routes/configs/test_version.py (2)
backend/app/models/llm/request.py (2)
ConfigBlob(61-67)CompletionConfig(49-58)backend/app/tests/utils/test_data.py (1)
create_test_version(283-317)
backend/app/models/llm/__init__.py (1)
backend/app/models/llm/request.py (4)
LLMCallRequest(129-148)CompletionConfig(49-58)QueryParams(35-46)ConfigBlob(61-67)
backend/app/tests/crud/config/test_config.py (4)
backend/app/models/llm/request.py (2)
ConfigBlob(61-67)CompletionConfig(49-58)backend/app/tests/crud/config/test_version.py (1)
example_config_blob(16-26)backend/app/crud/config/config.py (1)
ConfigCrud(19-159)backend/app/models/config/config.py (1)
ConfigCreate(56-71)
backend/app/models/__init__.py (1)
backend/app/models/llm/request.py (2)
ConfigBlob(61-67)CompletionConfig(49-58)
backend/app/tests/utils/test_data.py (3)
backend/app/models/llm/request.py (2)
ConfigBlob(61-67)CompletionConfig(49-58)backend/app/models/config/config.py (1)
ConfigBase(13-19)backend/app/tests/services/llm/providers/test_openai.py (1)
provider(27-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: checks (3.11.7, 6)
🔇 Additional comments (10)
backend/app/services/llm/jobs.py (2)
81-114: LGTM! Well-structured error handling.The
resolve_config_blobfunction provides robust error handling with distinct paths for expected (HTTPException) and unexpected exceptions, along with appropriate logging. The tuple return pattern clearly communicates success vs failure states.
133-180: Validation logic confirms code is safe—the review comment concern is unfounded.The
validate_config_logicmethod enforces mutual exclusivity (raises error if both stored config and blob provided), requires bothidandversionfor stored config, and requiresblobfor ad-hoc config. This guarantees that whenconfig.is_stored_configis False,config.blobis non-None (line 166), and when the stored path succeeds,config_blobis non-None. The error handling at line 159 prevents entry into line 168 whenconfig_blobwould be None, ensuringconfig_blobis never None when accessed.Likely an incorrect or invalid review comment.
backend/app/models/llm/__init__.py (1)
1-7: LGTM! Public exports updated correctly.The addition of
ConfigBlobto the public imports aligns with the new configuration management functionality and enables downstream modules to access this type.backend/app/crud/config/config.py (1)
50-50: LGTM! Correct serialization of ConfigBlob.The use of
config_blob.model_dump()properly serializes the typed ConfigBlob object to a dictionary for database storage, aligning with the new typed configuration structure.backend/app/crud/config/version.py (1)
37-37: LGTM! Consistent serialization pattern.The serialization of
config_blobusingmodel_dump()is consistent with the approach inbackend/app/crud/config/config.pyand correctly handles the typed ConfigBlob structure.backend/app/models/__init__.py (1)
90-91: LGTM! Public API surface expanded appropriately.Adding
ConfigBlobandCompletionConfigto the package-level exports enables consistent imports across the codebase and supports the new configuration management functionality.backend/app/tests/api/routes/configs/test_config.py (1)
20-29: LGTM! Tests updated to use nested configuration structure.The tests correctly use the new nested
config_blobstructure withcompletion.providerandcompletion.params, aligning with the ConfigBlob/CompletionConfig schema. This ensures the API accepts and validates the new configuration format.Also applies to: 89-94, 419-424
backend/app/models/config/config.py (1)
5-5: LGTM! Type safety improved with ConfigBlob.The change from
dict[str, Any]toConfigBlobprovides better type safety and validation. The import ofConfigBlobis correctly added, and the removal ofUniqueConstraintappears to be a cleanup (it wasn't used in the file).Also applies to: 9-9, 60-60
backend/app/tests/crud/config/test_config.py (2)
18-29: LGTM! Good use of fixture pattern.The
example_config_blobfixture follows the factory pattern for test fixtures and provides a reusable ConfigBlob instance with properly structured nested configuration. This improves test maintainability and consistency.Based on learnings, this aligns with the recommended approach for test fixtures.
32-57: LGTM! Tests correctly use fixture and verify serialization.The tests properly use the
example_config_blobfixture and verify that the stored blob matchesexample_config_blob.model_dump()(line 57), which correctly validates the serialization behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
backend/app/tests/api/routes/test_llm.py (1)
17-31: The payload structure correctly reflects the new API.The test successfully validates the ad-hoc config blob path. Consider adding tests for:
- Stored config path using
id+version- Validation scenarios: both methods provided, neither provided, or partial stored config (id without version or vice versa)
These additional tests would ensure the validation logic in
LLMCallConfigworks correctly at the API level.backend/app/tests/services/llm/test_jobs.py (2)
393-439: Consider reusingjob_envfixture to reduce duplication.The stored config tests duplicate the mock setup pattern from the
job_envfixture. Consider parameterizing or extending the fixture to support stored config scenarios.That said, the test logic is correct and provides good coverage for the stored config success path.
615-618: Move import to module level.The
ConfigVersionCreateimport should be at the top of the file with other imports for consistency and to avoid runtime import overhead on each test run.from app.models.llm.request import ConfigBlob, LLMCallConfig +from app.models.config import ConfigVersionCreate from app.services.llm.jobs import (Then remove line 617.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
backend/app/tests/api/routes/test_llm.py(2 hunks)backend/app/tests/services/llm/test_jobs.py(5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Use type hints in Python code (Python 3.11+ project)
Files:
backend/app/tests/api/routes/test_llm.pybackend/app/tests/services/llm/test_jobs.py
🧬 Code graph analysis (1)
backend/app/tests/api/routes/test_llm.py (1)
backend/app/models/llm/request.py (3)
LLMCallConfig(70-126)CompletionConfig(49-58)ConfigBlob(61-67)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: checks (3.11.7, 6)
🔇 Additional comments (8)
backend/app/tests/api/routes/test_llm.py (1)
4-9: LGTM!The imports correctly include all necessary types for the new configuration structure.
backend/app/tests/services/llm/test_jobs.py (7)
8-31: LGTM!The import additions are appropriate for the new stored config resolution tests. All imported symbols are utilized in the test code below.
41-49: LGTM!The fixture properly wraps
CompletionConfiginsideConfigBlob, aligning with the new dual-pathLLMCallConfigsemantics.
226-233: LGTM!The request data structure correctly reflects the new blob-wrapped completion config path.
491-524: LGTM!Good error handling coverage for the version-not-found scenario. The test correctly verifies that the job fails gracefully and returns an appropriate error message.
580-613: LGTM!Good defensive test that validates error handling for malformed configuration blobs. Manually corrupting the database record is an appropriate technique for testing this edge case.
650-670: LGTM!Thorough test coverage for multi-version scenarios. The test correctly verifies that each version resolves to its specific configuration values.
530-554: LGTM!Clean unit test that verifies the happy path for
resolve_config_blob, with thorough assertions on the resolved configuration values.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
backend/app/services/llm/jobs.py
Outdated
| else: | ||
| config_blob = config.blob | ||
|
|
||
| if callback is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this condition if callback is None?
if callback is present, should we not fetch the provider_instance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thats the response to callback if something fails in config retrieval,
this might be confusing changed callback to callback_response
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
backend/app/services/llm/jobs.py (1)
133-183: Guard againstconfig_blobbeingNonebefore accessingconfig_blob.completion.providerRight now the provider setup runs whenever
callback_response is None, and it unconditionally dereferencesconfig_blob.completion.provider. If upstream validation or future changes ever allow a case whereconfig_blobis stillNonewhilecallback_responseis alsoNone(e.g., malformed or missing inline blob), this will raise anAttributeErrorand fall into the generic “Unexpected error occurred” path instead of returning a clear configuration error.It’s safer to:
- Only call
get_llm_providerwhen bothcallback_response is Noneandconfig_blob is not None.- If
callback_response is still Nonebutconfig_blobisNone, synthesize a failure response so you never dereference a missing blob.For example:
- if callback_response is None: - try: - provider_instance = get_llm_provider( - session=session, - provider_type=config_blob.completion.provider, - project_id=project_id, - organization_id=organization_id, - ) - except ValueError as ve: - callback_response = APIResponse.failure_response( - error=str(ve), - metadata=request.request_metadata, - ) + if callback_response is None and config_blob is not None: + try: + provider_instance = get_llm_provider( + session=session, + provider_type=config_blob.completion.provider, + project_id=project_id, + organization_id=organization_id, + ) + except ValueError as ve: + callback_response = APIResponse.failure_response( + error=str(ve), + metadata=request.request_metadata, + ) + elif callback_response is None and config_blob is None: + callback_response = APIResponse.failure_response( + error="Resolved configuration blob is empty", + metadata=request.request_metadata, + )This aligns the control flow with the intent (“one of stored config or blob is guaranteed”) while making the failure mode explicit and avoiding any chance of dereferencing a
Noneblob.
🧹 Nitpick comments (1)
backend/app/services/llm/jobs.py (1)
219-223: Remove unnecessary f-string prefix in unexpected-error message
"Unexpected error occurred"doesn’t interpolate any variables, so thefprefix is redundant and Ruff flags it (F541). A plain string avoids the warning:- callback_response = APIResponse.failure_response( - error=f"Unexpected error occurred", - metadata=request.request_metadata, - ) + callback_response = APIResponse.failure_response( + error="Unexpected error occurred", + metadata=request.request_metadata, + )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
backend/app/services/llm/jobs.py(4 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Use type hints in Python code (Python 3.11+ project)
Files:
backend/app/services/llm/jobs.py
backend/app/services/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Implement business logic services under backend/app/services/
Files:
backend/app/services/llm/jobs.py
🪛 Ruff (0.14.6)
backend/app/services/llm/jobs.py
221-221: f-string without any placeholders
Remove extraneous f prefix
(F541)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: checks (3.11.7, 6)
🔇 Additional comments (1)
backend/app/services/llm/jobs.py (1)
81-114: Config resolution helper looks clean and well-factoredThe separation between fetching the stored config version and parsing it into
ConfigBlob, with(config_blob, error_message)as the contract, keepsexecute_jobstraightforward and centralizes error handling and logging. This helper looks good as-is.
…r error handling in execute_job function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
backend/app/models/llm/request.py (1)
91-97: Minor: Missing space in description string.There's a missing space between the two sentences in the description.
blob: ConfigBlob | None = Field( default=None, description=( - "Raw JSON blob of the full configuration. Used for ad-hoc configurations without storing." - "Either this or (id + version) must be provided." + "Raw JSON blob of the full configuration. Used for ad-hoc configurations without storing. " + "Either this or (id + version) must be provided." ), )backend/app/services/llm/jobs.py (1)
219-228: Remove extraneous f-prefix from string literal.The f-string at line 221 has no placeholders and should be a regular string.
except Exception as e: callback_response = APIResponse.failure_response( - error=f"Unexpected error occurred", + error="Unexpected error occurred", metadata=request.request_metadata, )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
backend/app/models/llm/request.py(2 hunks)backend/app/services/llm/jobs.py(4 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Use type hints in Python code (Python 3.11+ project)
Files:
backend/app/models/llm/request.pybackend/app/services/llm/jobs.py
backend/app/models/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Define SQLModel entities (database tables and domain objects) in backend/app/models/
Files:
backend/app/models/llm/request.py
backend/app/services/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Implement business logic services under backend/app/services/
Files:
backend/app/services/llm/jobs.py
🪛 Ruff (0.14.6)
backend/app/services/llm/jobs.py
221-221: f-string without any placeholders
Remove extraneous f prefix
(F541)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: checks (3.11.7, 6)
🔇 Additional comments (6)
backend/app/models/llm/request.py (3)
61-68: LGTM!Clean model definition with appropriate type hints and placeholder comments for future extensions.
99-127: LGTM!The validation logic correctly enforces mutual exclusivity between stored config (id+version) and ad-hoc blob, while ensuring both id and version are provided together when using stored config. The
is_stored_configproperty provides a clean interface for checking the configuration path.
129-163: LGTM!The updated docstring and field descriptions clearly document the dual-path configuration approach (stored vs blob) and provide appropriate production guidance. This addresses the prior review feedback about swagger documentation, as Field descriptions are exposed in the OpenAPI schema.
backend/app/services/llm/jobs.py (3)
81-114: LGTM!The function correctly handles both expected errors (HTTPException, validation errors) and unexpected exceptions with appropriate logging. The tuple return pattern for (result, error) is clear and facilitates clean error handling at the call site.
150-183: Config resolution flow looks correct; prior null-pointer concern is addressed.The early return at lines 164-166 now correctly handles the stored-config failure case, preventing null access on
config_blob. The else branch (line 168-169) assignsconfig.blobwhich is guaranteed non-None byLLMCallConfigvalidation.
185-217: LGTM!The success and failure paths correctly construct responses using
callback_responseand handle callback delivery and job status updates appropriately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
backend/app/services/llm/jobs.py (2)
133-170: Config resolution and provider invocation correctly routed throughConfigBlobThe updated
execute_jobflow looks sound:
- Relies on
LLMCallConfigvalidation, then branches onconfig.is_stored_config, ensuring only one of stored config or blob is used.- For stored configs, you resolve via
ConfigVersionCrudandresolve_config_blob, and on any retrieval/parsing error you immediately build anAPIResponse.failure_responseand delegate tohandle_job_error, soconfig_blobis never dereferenced when invalid.- For ad‑hoc configs, you directly assign
config_blob = config.blob, which is guaranteed non‑None by the model validator.provider_typeandcompletion_configare consistently sourced fromconfig_blob.completion, unifying both config paths.Given the model invariants and early‑return error handling,
config_blobwill always be non‑None where accessed here. If you want to appease stricter type checkers, you could optionally add anassert config_blob is not Nonebefore using it, but functionally this is correct.- try: - provider_instance = get_llm_provider( - session=session, - provider_type=config_blob.completion.provider, - project_id=project_id, - organization_id=organization_id, - ) + assert config_blob is not None + try: + provider_instance = get_llm_provider( + session=session, + provider_type=config_blob.completion.provider, + project_id=project_id, + organization_id=organization_id, + )Also applies to: 174-174, 186-186
220-228: Remove redundant f‑string in generic error response (linter F541)At line 221,
error=f"Unexpected error occurred"is an f‑string without any interpolation. While it works, it triggers a linter warning and is unnecessary.You can simplify it as:
- callback_response = APIResponse.failure_response( - error=f"Unexpected error occurred", - metadata=request.request_metadata, - ) + callback_response = APIResponse.failure_response( + error="Unexpected error occurred", + metadata=request.request_metadata, + )Everything else in this generic error handler (logging
str(e)and delegating tohandle_job_error) looks good.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
backend/app/services/llm/jobs.py(4 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Use type hints in Python code (Python 3.11+ project)
Files:
backend/app/services/llm/jobs.py
backend/app/services/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Implement business logic services under backend/app/services/
Files:
backend/app/services/llm/jobs.py
🧬 Code graph analysis (1)
backend/app/services/llm/jobs.py (6)
backend/app/crud/config/version.py (2)
ConfigVersionCrud(15-142)exists_or_raise(113-123)backend/app/crud/jobs.py (1)
JobCrud(11-42)backend/app/models/job.py (3)
JobStatus(9-13)JobType(16-18)JobUpdate(47-50)backend/app/models/llm/request.py (3)
ConfigBlob(61-67)LLMCallConfig(70-126)is_stored_config(124-126)backend/app/crud/config/config.py (1)
exists_or_raise(134-142)backend/app/utils.py (3)
APIResponse(30-54)failure_response(43-54)success_response(37-40)
🪛 Ruff (0.14.6)
backend/app/services/llm/jobs.py
221-221: f-string without any placeholders
Remove extraneous f prefix
(F541)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: checks (3.11.7, 6)
🔇 Additional comments (3)
backend/app/services/llm/jobs.py (3)
9-12: Imports correctly updated for config CRUD and typed LLM config modelsThe added imports for
ConfigVersionCrud,ConfigBlob, andLLMCallConfigmatch their new usage inresolve_config_blobandexecute_job, and keep the types explicit. No issues here.
81-115:resolve_config_blobhelper is well‑structured; error handling looks robustThe helper cleanly separates retrieval and parsing concerns:
- Uses
ConfigVersionCrud.exists_or_raisefor the stored version and converts theHTTPException.detailinto a user‑facing error string.- Catches parse issues when constructing
ConfigBlob(**config_version.config_blob)and returns a clear validation error.- Logs unexpected exceptions with config id/version context while returning generic, human‑safe error messages.
The type hints and return convention
(ConfigBlob | None, str | None)are clear and align with how the caller handles errors.
192-217: Success and failure response paths are consistent with centralized error handlingThe post‑execution handling is coherent:
- On non‑empty
response, you build anAPIResponse.success_response, optionally send a callback, mark the job asSUCCESS, log, and return the serialized response directly.- When
responseis falsy, you derive a failureAPIResponseusingerror or "Unknown error occurred"and route it throughhandle_job_error, which standardizes callback sending and job status updates.This keeps success and error paths explicit while centralizing the failure side effects in
handle_job_error.
Summary
Target issue is #439
Introduce support for referencing stored configurations using an identifier and version, allowing for more flexible configuration management. This change addresses the need for users to either provide a stored configuration or an ad-hoc configuration blob, ensuring that only one method is used at a time.
Checklist
Before submitting a pull request, please ensure that you mark these task.
fastapi run --reload app/main.pyordocker compose upin the repository root and test.Notes
Please add here if any other information is required for the reviewer.
Summary by CodeRabbit
New Features
Improvements
Models
Tests
✏️ Tip: You can customize this high-level summary in your review settings.