Skip to content

Release 1.0.0 - #2

Merged
kiranharidas187 merged 12 commits into
ELEVATE-Project:release-1.0.0from
darshilbabel:release-1.0.0
Jun 1, 2026
Merged

Release 1.0.0#2
kiranharidas187 merged 12 commits into
ELEVATE-Project:release-1.0.0from
darshilbabel:release-1.0.0

Conversation

@KUNALTEMPEST

@KUNALTEMPEST KUNALTEMPEST commented Jun 1, 2026

Copy link
Copy Markdown

Summary by CodeRabbit

  • New Features

    • Added external LLM gateway integration with streaming support.
    • Introduced vector knowledge-base search capability.
    • Added web search feature with configurable context size.
    • Added PDF and DOCX file generation.
  • Enhancements

    • Extended LLM provider support with Anthropic and Claude model variants.
    • Improved response handling with tool execution and source tracking.
  • Chores

    • Removed admin interfaces for stories and themes.
    • Updated project configuration and environment variable handling.

… and chunk persistence

- Add download_file handler in CommonResponseHandler generating both PDF (Jinja2+Gotenberg) and DOCX (python-docx) and saving both URLs to CompanyChat.other_params and WebSocket extra_content
- Add render_template_to_pdf (Flow/PDFTemplates lookup, Jinja2 context with args/constants/profile/sources) and create_docx_from_args (structured MIP sections + References)
- Add sanitize_filename with extension param and MediaTypeChoices.DOCX
- Wire finalized_sources through respond_to_user tool: save to ChatSession.other_params on each call, inject into system prompt each turn, use at download_file time for References section in both formats
- Fix chunk accumulation in tool loop: retrieved_chunks now a list extended across all iterations instead of overwritten; pass through to process_response via extra dict key _retrieved_chunks
- Fix chunks not saved to DB: serialize as JSON string (TextField was storing Python repr); add _safe_json_dumps helper with silent fallback
- Append Sources used block to assistant messages in chat history when chunks are present, enabling LLM to track which sources backed accepted content
- Add citation chunk extraction for streaming path: call_llm_gateway_stream yields 4-tuple with citations; _handle_gateway_stream merges KB + citation chunks before save
- Fix _handle_freeflow_function_call routing: explicit _freeflow_action_tools / _json_message_tools dispatch in process_response
- Fix respond_to_user message extraction: fall back to response key when message key absent; extract quick_reply_chips
- Format KB search results with Source: [Title](url) header so LLM can cite them
Skip web-search retry when LLM returns a non-empty response — the
tokens were already streamed to the client, so retrying caused a second
complete message to appear.

For download_file: when the LLM streams text before calling the tool,
signal this via _text_streamed_to_ws so _handle_freeflow_function_call
sends only a stop chunk with the download URLs instead of repeating the
bot_message through translate_and_send_message.
- Extract usage (input/output tokens, cost) from gateway responses for
  both streaming and non-streaming paths
- Accumulate full turn cost across tool-loop iterations (KB search +
  retries) so CompanyChat.other_params reflects the total turn spend,
  not just the final call
- Update ChatSession.other_params with running totals after every LLM
  call
- Fix CompanyChat query to filter by sender__id=1 (bot profile) instead
  of the non-existent initiated_by field
- Yield usage data from stream finish event so streaming path tracks
  cost the same way as non-stream
- Normalize respond_to_user tool args (quick_reply_chips, finalized_sources)
  that Llama returns as JSON strings instead of arrays
- Embed hyperlinks in DOCX references section instead of raw URL text
@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR integrates an external LLM gateway service to replace provider-specific OpenAI/Bedrock handling, adds vector knowledge-base and web-search query capabilities to CompanyBot, introduces PDF template and DOCX generation with hyperlinks, and refactors response handlers to execute tools iteratively through the gateway. It also updates Celery tasks to support message appending, converts configuration to environment-driven values, and disables Django admin interfaces.

Changes

LLM Gateway Integration & Schema Updates

Layer / File(s) Summary
Schema updates: enums, migrations, and CompanyBot configuration
chatbot/models/enums.py, chatbot/models/company_models.py, chatbot/migrations/0082_*, chatbot/migrations/0083_*, chatbot/migrations/0084_*, observability/migrations/0007_*, observability/migrations/0008_*
Removes BEDROCK_CONVERSE, adds ANTHROPIC provider and Claude 3/3.5/3.7/4.5 models, adds WebSearchContextSize enum with LOW/MEDIUM/HIGH, adds DOCX media type, and extends CompanyBot with use_vector_service, enable_web_search, and web_search_context_size fields via migrations.
LLM gateway client module
chatbot/llm_models/llm_gateway.py
Introduces build_gateway_params, call_llm_gateway, and call_llm_gateway_stream to handle HTTP POST requests to external gateway's /v1/chat/ and /v1/chat/stream endpoints with tool support, error logging, and citation/token accumulation.
Vector knowledge-base search service
chatbot/services/vector/vector_service.py
Adds _fetch_chunks to query vector database with score/length filtering and fetch_context_for_query to format retrieved chunks into context strings for LLM augmentation.
Prompt building and orchestrator updates
chatbot/services/core/prompt_builder.py, chatbot/services/core/orchestrator.py
Refactors build_system_prompt to render Jinja2 tag context and execute SQL dynamic context; augments chat orchestrator to append finalized sources block to system prompt.
Base response handler: gateway integration and tool execution
chatbot/services/response_handlers/base_response_handler.py
Routes LLM calls through gateway, implements iterative tool-execution loop (max 5 iterations) supporting search_knowledge_base and respond_to_user, extracts and persists citations/sources, and manages per-turn usage tracking for both streaming and non-streaming modes.
Common response handler: function call routing and JSON tool handling
chatbot/services/response_handlers/common_handler.py
Detects non-state-machine function calls, routes download_file/respond_to_user/process_user_input to specialized handlers, merges extra content, persists finalized sources, and handles SIMPLE-bot response normalization.

Media Generation & Chat Utilities

Layer / File(s) Summary
Media generation: PDF templates and DOCX with hyperlinks
chatbot/utils/media_preview/media_creation.py
Adds _add_hyperlink helper, generalizes sanitize_filename with extension parameter, introduces render_template_to_pdf for Flow-based Jinja template rendering via Gotenberg, and introduces create_docx_from_args for MIP and knowledge document generation with reference section hyperlinks.
Chat utilities: OpenAI formatting with sources
chatbot/utils/chat_utils.py
Updates format_message_as_per_openai_format to append "Sources used" section from CompanyChat chunks JSON; simplifies get_guided_chat to unconditionally return OpenAI-formatted messages.
Download file: PDF/DOCX template rendering and streaming
chatbot/services/response_handlers/common_handler.py
Completely refactors FREE_FLOW download_file to render PDF/DOCX from templates using finalized sources from session other_params, includes retry on dual failure, conditionally sends only URLs if text was already streamed, and persists function metadata/URLs to company database.

Persistence & Configuration

Layer / File(s) Summary
Celery task: append-to-last message handling
chatbot/celery_tasks/common_chat_tasks.py
Introduces _safe_json_dumps helper, extends save_in_company_db with append_to_last parameter, conditionally appends/overwrites last CompanyChat message, and stores chunks via safe JSON serialization.
Django/Celery configuration and environment setup
shikshalokam_mohini/celery_config.py, shikshalokam_mohini/settings.py, pyproject.toml, sample.env
Reads REDIS_DB from environment for Celery URLs, switches SECRET_KEY to environment-driven value, updates project name to saathi-backend, pins google-cloud-storage>=3.10.1, and converts sample.env to template with LLM gateway variables.
WebSocket routing and admin cleanup
chatbot/routing.py, chatbot/admin/story_admin.py, chatbot/admin/theme_admin.py
Reorders ws/common/ route; comments out entire story_admin.py and theme_admin.py Django admin registrations, inlines, and methods.

🎯 4 (Complex) | ⏱️ ~75 minutes

🐰 Hops into the LLM gateway, whiskers twitching with glee,
Vector contexts dance, web searches flow free,
PDFs and DOCX files hop off the screen,
The finest refactor this warren has seen! 🌟

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 76.19% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Release 1.0.0' is vague and generic; it does not describe the actual changes being made (vector/LLM services integration, web search, PDF/DOCX generation, usage tracking, etc.). Consider a more descriptive title that summarizes the main change, such as 'Integrate vector service, LLM gateway, and web search with tool-based file generation' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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 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 and usage tips.

Warning

⚠️ This pull request might be slop. It has been flagged by CodeRabbit slop detection and should be reviewed carefully.

@KUNALTEMPEST

Copy link
Copy Markdown
Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

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

⚠️ Outside diff range comments (2)
chatbot/admin/story_admin.py (1)

1-184: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Delete the commented-out story_admin.py (or explicitly re-enable admin functionality)

  • chatbot/admin/__init__.py imports from .story_admin import *, so with chatbot/admin/story_admin.py fully commented out, StoryAdmin/StoryTranslationAdmin registrations and the admin-only functionality (export routes, PDF hooks in save_model, post-processing route) will not be available.
  • If removal is intended, delete chatbot/admin/story_admin.py; if it’s temporary, replace the commented file with a minimal stub and add a clear TODO/expiry note stating when it will be restored.
🤖 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 `@chatbot/admin/story_admin.py` around lines 1 - 184, The file
chat_admin/story_admin.py is fully commented out but is imported by
chatbot/admin/__init__.py causing admin registrations and routes (StoryAdmin,
StoryTranslationAdmin, export_stories_view, save_model PDF hooks,
PostProcessingView route) to be missing; either delete story_admin.py if removal
is intentional, or restore minimal admin functionality by re-enabling the
StoryAdmin and StoryTranslationAdmin registrations (or create a minimal stub
that defines StoryAdmin and StoryTranslationAdmin as no-op admin.ModelAdmin
subclasses or safely guards the import) and add a clear TODO comment with an
expiry date; ensure the symbols StoryAdmin, StoryTranslationAdmin,
export_stories_view (or PostProcessingView route), and save_model logic are
present or stubbed so chatbot/admin/__init__.py import no longer breaks.
chatbot/models/company_models.py (1)

73-94: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Remove the duplicate provider / provider_keys field definitions.

provider and provider_keys are each declared twice (Lines 73-76 and again Lines 87-94). Since these are class attributes, the second definitions silently shadow the first, making Lines 73-76 dead code. This is confusing and a maintenance hazard — keep only the intended definition (the one with default=LLMProvider.BEDROCK and the updated help_text).

♻️ Proposed cleanup
-    provider = models.CharField(
-        max_length=100, choices=LLMProvider.choices, default=LLMProvider.OPENAI)
-    provider_keys = models.TextField(
-        default="", max_length=1000, null=False, blank=True)
     bot_temperature = models.FloatField(
🤖 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 `@chatbot/models/company_models.py` around lines 73 - 94, The model defines
provider and provider_keys twice causing the first declarations to be shadowed;
remove the duplicate early definitions and keep the intended variants that use
default=LLMProvider.BEDROCK and include the help_text. Specifically, delete the
initial provider = models.CharField(...) and provider_keys =
models.TextField(...) occurrences and ensure only the provider and provider_keys
fields with default=LLMProvider.BEDROCK and the updated help_text remain in the
model (referencing the provider and provider_keys attributes and LLMProvider
choices).
🧹 Nitpick comments (10)
chatbot/admin/theme_admin.py (1)

1-40: ⚡ Quick win

Delete the file rather than commenting out all code.

Same concern as story_admin.py — if Theme admin is being permanently disabled, remove the file entirely instead of leaving commented code. If temporary, document why.

🤖 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 `@chatbot/admin/theme_admin.py` around lines 1 - 40, The file contains a fully
commented-out Django admin class (ThemeAdmin) and related imports (Theme,
ThemeType, get_form, changeform_view) — remove the file entirely if the Theme
admin is permanently disabled; if it's temporary, restore a minimal, documented
placeholder (keep a short module-level comment explaining why it's disabled and
a TODO with an expected re-enable date or issue ref) or re-enable by
uncommenting and ensuring ThemeAdmin, get_form and changeform_view are correct;
commit the deletion or the documented placeholder so the repo no longer contains
a whole commented-out implementation.
shikshalokam_mohini/settings.py (1)

54-54: 💤 Low value

Optional: fail fast with a clear message when DJANGO_SECRET_KEY is missing.

os.getenv('DJANGO_SECRET_KEY') returns None when the variable is unset. Django will eventually raise, but the error surfaces late and indirectly (and SIGNING_KEY = SECRET_KEY on Line 372 would silently become None for JWT). A guard makes misconfiguration obvious at startup.

♻️ Proposed guard
-SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
+SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
+if not SECRET_KEY:
+    raise ValueError("DJANGO_SECRET_KEY environment variable is required")
🤖 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 `@shikshalokam_mohini/settings.py` at line 54, SECRET_KEY is set from
os.getenv('DJANGO_SECRET_KEY') which can be None; add a fail-fast guard in
settings so that if SECRET_KEY is falsy you raise a clear exception at import
time. Locate the SECRET_KEY assignment and follow-up use of SIGNING_KEY
(SIGNING_KEY = SECRET_KEY) and replace with logic that validates SECRET_KEY
(e.g., check SECRET_KEY after assignment) and raise a RuntimeError or
ImproperlyConfigured with a clear message instructing to set DJANGO_SECRET_KEY
when missing.
chatbot/utils/media_preview/media_creation.py (1)

291-295: 💤 Low value

Remove debug print() statements.

Lines 291, 293, and 295 use print() for diagnostics that are already covered by the logger.info call on Line 297. Drop the prints to avoid noisy stdout in production.

🤖 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 `@chatbot/utils/media_preview/media_creation.py` around lines 291 - 295, Remove
the three debug print() calls around flow lookup and PDF template retrieval;
rely on the existing logger.info call instead. Specifically, delete the
print("flow_route: ", flow_name), print("Flow found: ", flow) and print("PDF
Template: ", pdf_template) lines that appear around the flow_name/flow and
PDFTemplates.objects.filter(...).first() calls so the code only uses the
logger.info message that follows. Ensure no other side-effects remain after
removing these print statements.
chatbot/llm_models/llm_gateway.py (1)

63-63: ⚡ Quick win

Consider making the timeout configurable.

The 120-second timeout is hard-coded in both call_llm_gateway and call_llm_gateway_stream. Different LLM models, request sizes, or deployment environments may require different timeout values. Consider reading from an environment variable or accepting it as a parameter.

♻️ Proposed refactor to make timeout configurable
+_DEFAULT_TIMEOUT = int(os.getenv('LLM_GATEWAY_TIMEOUT', '120'))
+
 def call_llm_gateway(
     messages: list, provider: str, model: str, params: dict = None, tools: list = None,
-    tool_choice=None,
+    tool_choice=None, timeout: int = None,
 ) -> dict | None:
     """
     POST to /v1/chat/ on the LLM gateway service.
     """
+    timeout = timeout or _DEFAULT_TIMEOUT
     # ... existing code ...
     try:
-        response = requests.post(url, headers=headers, json=payload, timeout=120)
+        response = requests.post(url, headers=headers, json=payload, timeout=timeout)

Apply the same pattern to call_llm_gateway_stream.

🤖 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 `@chatbot/llm_models/llm_gateway.py` at line 63, The hard-coded 120s timeout in
call_llm_gateway and call_llm_gateway_stream should be made configurable: add a
timeout parameter to both functions with a default value (e.g., 120) and/or read
a fallback from an environment variable (e.g., LLM_GATEWAY_TIMEOUT parsed as
int), then replace the literal 120 in the requests.post timeout argument with
that variable; ensure you validate/convert the env var to an int and preserve
current behavior when not set.
chatbot/services/response_handlers/common_handler.py (1)

736-740: 💤 Low value

Consider making the response transformation more explicit.

The current code mutates the response dict in place using pop(), clear(), and update(). While functionally correct, this mutation pattern can be surprising to readers. Consider extracting the normalized data first, then reassigning.

♻️ Proposed refactor for clarity
         if company_bot.bot_type == CompanyBotTypeChoices.SIMPLE:
             if response and isinstance(response, dict):
-                extracted_data = response.pop("parameters", response.pop("input", None))
-                if extracted_data and isinstance(extracted_data, dict):
-                    response.clear()
-                    response.update(extracted_data)
+                extracted_data = response.get("parameters") or response.get("input")
+                if extracted_data and isinstance(extracted_data, dict):
+                    response = extracted_data

Note: This requires updating the function signature to return the potentially new response value, or accepting that the original caller's reference remains unchanged.

🤖 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 `@chatbot/services/response_handlers/common_handler.py` around lines 736 - 740,
The current in-place mutation of the response dict (using response.pop(...),
response.clear(), response.update(...)) is surprising; instead, read the
normalized data into a new variable (e.g., normalized =
response.get("parameters") or response.get("input")), check it is a dict, then
either assign response = normalized (and update the function signature to return
the possibly-new response) or explicitly replace the original mapping with a new
dict via a single assignment to avoid pop/clear/update side effects; refer to
the response variable and the "parameters"/"input" keys to locate and replace
the mutation logic in common_handler.py.
chatbot/services/response_handlers/base_response_handler.py (2)

394-394: ⚡ Quick win

Replace debug print statements with logger calls.

Multiple debug print statements throughout this file bypass the logging infrastructure. Convert them to logger.debug() calls to ensure they're captured by log aggregation tools and can be filtered by log level in production.

♻️ Example conversion
-print(f'[tool_loop] iteration={iteration} result={str(result)[:200]}')
+logger.debug(f'[tool_loop] iteration={iteration} result={str(result)[:200]}')

-print("="*50)
-print("Result: ", result)
-print("="*50)
+logger.debug("="*50)
+logger.debug("Result: %s", result)
+logger.debug("="*50)

Apply similar changes to all print statements in this file.

Also applies to: 396-398, 526-526, 602-602, 636-636, 672-672, 756-758

🤖 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 `@chatbot/services/response_handlers/base_response_handler.py` at line 394,
Replace all direct print(...) debug statements in base_response_handler.py with
logger.debug(...) so logs flow through the app's logging infra; specifically
update the print in the tool_loop function (the line printing iteration and
result), and the other prints noted (around the blocks that currently print
debug info at the locations you flagged) to call the module/class logger (e.g.,
self.logger.debug(...) if inside instance methods or logger.debug(...) for
module-level code). Ensure a logger is available in the scope (use an existing
logger variable or add: logger = logging.getLogger(__name__) or attach
self.logger in the class constructor) and preserve the original message
formatting (truncate result like str(result)[:200]) when converting to
logger.debug calls.

363-363: ⚡ Quick win

Extract max_iterations as a class constant.

The value 5 for maximum tool iterations is hard-coded. Consider extracting it as a class constant (e.g., MAX_TOOL_ITERATIONS = 5) in __init__ to make it easier to adjust for different bot configurations or to document the rationale for this limit.

🤖 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 `@chatbot/services/response_handlers/base_response_handler.py` at line 363, The
hard-coded local variable max_iterations = 5 in BaseResponseHandler should be
turned into a class-level constant so it’s configurable and documented; add a
constant like MAX_TOOL_ITERATIONS = 5 on the BaseResponseHandler class (or
assign self.MAX_TOOL_ITERATIONS in __init__ if instance-level is preferred),
then replace usages of max_iterations with that constant (e.g., in the method
referencing max_iterations) and update any docstring or comment to explain the
rationale.
chatbot/services/vector/vector_service.py (2)

11-11: ⚡ Quick win

Replace print statements with logger calls.

Debug print statements at lines 11 and 38 will bypass the logging infrastructure and won't be captured by log aggregation tools. Use the existing logger instance instead for consistent observability.

♻️ Proposed refactor
-    print("result: ", result)
+    logger.debug(f'[vector_service] query result: {result}')
-    print(f'[vector_service] query="{query}" → 0 chunks found')
+    # (This line can be removed since logger.info already logs the same information on line 37)

Also applies to: 38-38

🤖 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 `@chatbot/services/vector/vector_service.py` at line 11, Replace the direct
print calls in chatbot/services/vector/vector_service.py (the occurrences
printing "result: " and any other debug prints) with the module's logger
instance (e.g., logger.debug or logger.info as appropriate) so logs flow through
the existing logging infrastructure; locate the prints (e.g., the print("result:
", result) and the second debug print) and change them to logger.debug(f"result:
{result}") or logger.info(...) depending on desired level, preserving the
message content and variable interpolation.

18-18: 💤 Low value

Consider extracting the minimum text length threshold as a constant.

The value 20 for minimum text length is hard-coded. Extracting it as a module-level constant (e.g., _MIN_CHUNK_TEXT_LENGTH = 20) would make it easier to tune for different knowledge bases or use cases.

🤖 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 `@chatbot/services/vector/vector_service.py` at line 18, The hard-coded minimum
chunk length (20) in the condition "if text and len(text) > 20 and score >=
filter_score:" should be extracted to a module-level constant (e.g.,
_MIN_CHUNK_TEXT_LENGTH = 20) and the condition updated to use that constant
(len(text) > _MIN_CHUNK_TEXT_LENGTH); update any related docstring/comments and
tests that reference the magic number so the threshold is easy to tune for
different knowledge bases and use cases.
chatbot/services/core/orchestrator.py (1)

76-76: ⚡ Quick win

Remove unused import.

The json module is imported but not used in this code block. The sources block is constructed using string formatting without JSON serialization.

♻️ Proposed fix
             finalized_sources = (chat_session.other_params or {}).get('finalized_sources')
             if finalized_sources:
-                import json as _json
                 sources_block = '\n'.join(
                     f'- {s.get("title", "")} — {s.get("url", "")}' for s in finalized_sources
                 )
🤖 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 `@chatbot/services/core/orchestrator.py` at line 76, Remove the unused import
"import json as _json" from the module; the symbol _json is never referenced
when building the sources string, so delete that import line (or consolidate
imports if needed) to eliminate the unused dependency and linter warning in
orchestrator.py.
🤖 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 `@chatbot/celery_tasks/common_chat_tasks.py`:
- Around line 14-20: _safe_json_dumps currently re-serializes string inputs
which double-encodes pre-serialized payloads like `chunks`; update
_safe_json_dumps so it returns string inputs unchanged (e.g., if
isinstance(value, str): return value) before attempting json.dumps, keep the
None check and the try/except for non-string values to preserve existing
error-safe behavior.
- Around line 44-46: The append branch for append_to_last can raise TypeError
when message is None; in the function/block that updates last_chat.message
(referencing variables append_to_last, last_chat, and message) guard against
None by normalizing message to an empty string before concatenation (e.g., use
(message or '') or skip the append when message is None) so the expression
(last_chat.message or '') + '\n\n' + message never tries to add None to a str;
update that assignment accordingly.

In `@chatbot/llm_models/llm_gateway.py`:
- Around line 8-10: The module currently sets _API_KEY and _TENANT_ID to empty
strings by default which can silently produce auth failures; add validation that
checks _API_KEY and _TENANT_ID at module load (or at first use in the function
that sends requests) and raise a clear exception (e.g., ValueError) if either is
missing, so code using _API_KEY/_TENANT_ID (refer to those symbols) fails fast
with a descriptive message instead of sending empty Authorization or X-Tenant-Id
headers.

In `@chatbot/utils/media_preview/media_creation.py`:
- Around line 407-413: The NameError occurs because title_text is referenced but
never set in the non-MIP branch; fix by deriving title_text from the passed
arguments before calling doc.add_heading — e.g. set title_text =
arguments.get('title') or fallback to arguments.get('knowledge_title') or a
sensible default like "Document" — then use that title_text when calling
doc.add_heading and keep the existing loop that writes knowledge_content; update
the block around doc.add_heading, content = arguments.get('knowledge_content',
''), and the subsequent paragraph loop to use the new title_text variable.

In `@sample.env`:
- Around line 1-54: The environment variable template is missing several
variables used in settings.py and celery_config.py such as REDIS_HOST,
REDIS_PORT, REDIS_USE_SSL, REDIS_DB, PG_SSL_MODE, PG_SSL_ROOT_CERT,
CSRF_TRUSTED_ORIGINS, SENTRY_DSN, and the GCP/Azure storage keys
GCS_BUCKET_NAME, GCP_PROJECT_ID, GCP_CREDENTIALS_PATH, AZURE_ACCOUNT_NAME,
AZURE_ACCOUNT_KEY, and AZURE_CONTAINER_NAME. To fix this, add these missing
variables with appropriate placeholders or default values in the template to
clearly document them and prevent deployment issues.

---

Outside diff comments:
In `@chatbot/admin/story_admin.py`:
- Around line 1-184: The file chat_admin/story_admin.py is fully commented out
but is imported by chatbot/admin/__init__.py causing admin registrations and
routes (StoryAdmin, StoryTranslationAdmin, export_stories_view, save_model PDF
hooks, PostProcessingView route) to be missing; either delete story_admin.py if
removal is intentional, or restore minimal admin functionality by re-enabling
the StoryAdmin and StoryTranslationAdmin registrations (or create a minimal stub
that defines StoryAdmin and StoryTranslationAdmin as no-op admin.ModelAdmin
subclasses or safely guards the import) and add a clear TODO comment with an
expiry date; ensure the symbols StoryAdmin, StoryTranslationAdmin,
export_stories_view (or PostProcessingView route), and save_model logic are
present or stubbed so chatbot/admin/__init__.py import no longer breaks.

In `@chatbot/models/company_models.py`:
- Around line 73-94: The model defines provider and provider_keys twice causing
the first declarations to be shadowed; remove the duplicate early definitions
and keep the intended variants that use default=LLMProvider.BEDROCK and include
the help_text. Specifically, delete the initial provider = models.CharField(...)
and provider_keys = models.TextField(...) occurrences and ensure only the
provider and provider_keys fields with default=LLMProvider.BEDROCK and the
updated help_text remain in the model (referencing the provider and
provider_keys attributes and LLMProvider choices).

---

Nitpick comments:
In `@chatbot/admin/theme_admin.py`:
- Around line 1-40: The file contains a fully commented-out Django admin class
(ThemeAdmin) and related imports (Theme, ThemeType, get_form, changeform_view) —
remove the file entirely if the Theme admin is permanently disabled; if it's
temporary, restore a minimal, documented placeholder (keep a short module-level
comment explaining why it's disabled and a TODO with an expected re-enable date
or issue ref) or re-enable by uncommenting and ensuring ThemeAdmin, get_form and
changeform_view are correct; commit the deletion or the documented placeholder
so the repo no longer contains a whole commented-out implementation.

In `@chatbot/llm_models/llm_gateway.py`:
- Line 63: The hard-coded 120s timeout in call_llm_gateway and
call_llm_gateway_stream should be made configurable: add a timeout parameter to
both functions with a default value (e.g., 120) and/or read a fallback from an
environment variable (e.g., LLM_GATEWAY_TIMEOUT parsed as int), then replace the
literal 120 in the requests.post timeout argument with that variable; ensure you
validate/convert the env var to an int and preserve current behavior when not
set.

In `@chatbot/services/core/orchestrator.py`:
- Line 76: Remove the unused import "import json as _json" from the module; the
symbol _json is never referenced when building the sources string, so delete
that import line (or consolidate imports if needed) to eliminate the unused
dependency and linter warning in orchestrator.py.

In `@chatbot/services/response_handlers/base_response_handler.py`:
- Line 394: Replace all direct print(...) debug statements in
base_response_handler.py with logger.debug(...) so logs flow through the app's
logging infra; specifically update the print in the tool_loop function (the line
printing iteration and result), and the other prints noted (around the blocks
that currently print debug info at the locations you flagged) to call the
module/class logger (e.g., self.logger.debug(...) if inside instance methods or
logger.debug(...) for module-level code). Ensure a logger is available in the
scope (use an existing logger variable or add: logger =
logging.getLogger(__name__) or attach self.logger in the class constructor) and
preserve the original message formatting (truncate result like
str(result)[:200]) when converting to logger.debug calls.
- Line 363: The hard-coded local variable max_iterations = 5 in
BaseResponseHandler should be turned into a class-level constant so it’s
configurable and documented; add a constant like MAX_TOOL_ITERATIONS = 5 on the
BaseResponseHandler class (or assign self.MAX_TOOL_ITERATIONS in __init__ if
instance-level is preferred), then replace usages of max_iterations with that
constant (e.g., in the method referencing max_iterations) and update any
docstring or comment to explain the rationale.

In `@chatbot/services/response_handlers/common_handler.py`:
- Around line 736-740: The current in-place mutation of the response dict (using
response.pop(...), response.clear(), response.update(...)) is surprising;
instead, read the normalized data into a new variable (e.g., normalized =
response.get("parameters") or response.get("input")), check it is a dict, then
either assign response = normalized (and update the function signature to return
the possibly-new response) or explicitly replace the original mapping with a new
dict via a single assignment to avoid pop/clear/update side effects; refer to
the response variable and the "parameters"/"input" keys to locate and replace
the mutation logic in common_handler.py.

In `@chatbot/services/vector/vector_service.py`:
- Line 11: Replace the direct print calls in
chatbot/services/vector/vector_service.py (the occurrences printing "result: "
and any other debug prints) with the module's logger instance (e.g.,
logger.debug or logger.info as appropriate) so logs flow through the existing
logging infrastructure; locate the prints (e.g., the print("result: ", result)
and the second debug print) and change them to logger.debug(f"result: {result}")
or logger.info(...) depending on desired level, preserving the message content
and variable interpolation.
- Line 18: The hard-coded minimum chunk length (20) in the condition "if text
and len(text) > 20 and score >= filter_score:" should be extracted to a
module-level constant (e.g., _MIN_CHUNK_TEXT_LENGTH = 20) and the condition
updated to use that constant (len(text) > _MIN_CHUNK_TEXT_LENGTH); update any
related docstring/comments and tests that reference the magic number so the
threshold is easy to tune for different knowledge bases and use cases.

In `@chatbot/utils/media_preview/media_creation.py`:
- Around line 291-295: Remove the three debug print() calls around flow lookup
and PDF template retrieval; rely on the existing logger.info call instead.
Specifically, delete the print("flow_route: ", flow_name), print("Flow found: ",
flow) and print("PDF Template: ", pdf_template) lines that appear around the
flow_name/flow and PDFTemplates.objects.filter(...).first() calls so the code
only uses the logger.info message that follows. Ensure no other side-effects
remain after removing these print statements.

In `@shikshalokam_mohini/settings.py`:
- Line 54: SECRET_KEY is set from os.getenv('DJANGO_SECRET_KEY') which can be
None; add a fail-fast guard in settings so that if SECRET_KEY is falsy you raise
a clear exception at import time. Locate the SECRET_KEY assignment and follow-up
use of SIGNING_KEY (SIGNING_KEY = SECRET_KEY) and replace with logic that
validates SECRET_KEY (e.g., check SECRET_KEY after assignment) and raise a
RuntimeError or ImproperlyConfigured with a clear message instructing to set
DJANGO_SECRET_KEY when missing.
🪄 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: 78931d06-c947-4223-8575-2c971fe9e37a

📥 Commits

Reviewing files that changed from the base of the PR and between d18eef1 and 6e993d4.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (24)
  • chatbot/admin/story_admin.py
  • chatbot/admin/theme_admin.py
  • chatbot/celery_tasks/common_chat_tasks.py
  • chatbot/llm_models/llm_gateway.py
  • chatbot/migrations/0082_companybot_use_vector_service_and_more.py
  • chatbot/migrations/0083_alter_companybot_llm_model_alter_companybot_provider_and_more.py
  • chatbot/migrations/0084_companybot_enable_web_search_and_more.py
  • chatbot/models/company_models.py
  • chatbot/models/enums.py
  • chatbot/routing.py
  • chatbot/services/core/orchestrator.py
  • chatbot/services/core/prompt_builder.py
  • chatbot/services/response_handlers/base_response_handler.py
  • chatbot/services/response_handlers/common_handler.py
  • chatbot/services/vector/__init__.py
  • chatbot/services/vector/vector_service.py
  • chatbot/utils/chat_utils.py
  • chatbot/utils/media_preview/media_creation.py
  • observability/migrations/0007_alter_botruntestcasemap_metric_name_and_more.py
  • observability/migrations/0008_alter_companybottcrun_llm_model_and_more.py
  • pyproject.toml
  • sample.env
  • shikshalokam_mohini/celery_config.py
  • shikshalokam_mohini/settings.py
💤 Files with no reviewable changes (1)
  • chatbot/routing.py

Comment thread chatbot/celery_tasks/common_chat_tasks.py
Comment thread chatbot/celery_tasks/common_chat_tasks.py
Comment thread chatbot/llm_models/llm_gateway.py
Comment thread chatbot/utils/media_preview/media_creation.py
Comment thread sample.env
@kiranharidas187
kiranharidas187 merged commit f2739ed into ELEVATE-Project:release-1.0.0 Jun 1, 2026
1 check passed
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.

2 participants