Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@Dishant1804
Copy link
Collaborator

Proposed change

Resolves #2406

  • improved the response of RAG
  • moved system prompts to prompt model
  • website links given in the response are properly formatted

Checklist

  • I've read and followed the contributing guidelines.
  • I've run make check-test locally; all checks and tests passed.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 9, 2025

Summary by CodeRabbit

  • New Features

    • Prompts for RAG answers and Slack question detection are now configurable, enabling updates without code changes.
    • Slack messages now auto-format Markdown-style links to Slack’s native link format for clearer previews.
  • Changes

    • Increased default retrieval limit from 5 to 8 and lowered similarity threshold from 0.4 to 0.1, broadening search results.
  • Tests

    • Expanded test coverage for dynamic prompts, error handling, OpenAI response scenarios, and updated defaults.

Walkthrough

Replaces hard-coded system prompts with dynamic Prompt model getters, updates default retrieval constants, adds Slack Markdown-to-Slack-link formatting and integrates it into Slack blocks, and updates tests to mock/use the new prompt getters and new defaults. No public API signature removals; two new Prompt accessors and one new Slack util added.

Changes

Cohort / File(s) Change summary
Dynamic prompts via Prompt model
backend/apps/core/models/prompt.py, backend/apps/ai/agent/tools/rag/generator.py, backend/apps/slack/common/question_detector.py, backend/tests/apps/ai/agent/tools/rag/generator_test.py, backend/tests/apps/slack/common/question_detector_test.py
Added Prompt.get_rag_system_prompt and Prompt.get_slack_question_detector_prompt. RAG generator and Slack question detector now retrieve system prompts via these getters (raising ObjectDoesNotExist if missing/empty). Tests updated to patch/expect the new getters and to assert prompt-related error cases.
Retrieval defaults updated
backend/apps/ai/common/constants.py, backend/tests/apps/ai/agent/tools/rag/rag_tool_test.py, backend/tests/apps/ai/management/commands/ai_run_rag_tool_test.py
Changed DEFAULT_CHUNKS_RETRIEVAL_LIMIT 5 → 8 and DEFAULT_SIMILARITY_THRESHOLD 0.4 → 0.1. Tests updated to expect limit=8 and similarity_threshold=0.1 in retriever/query call sites.
Slack link formatting
backend/apps/slack/utils.py, backend/apps/slack/blocks.py
Added format_links_for_slack(text: str) -> str to convert Markdown links [text](url) to Slack format `<url

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • RAG tool for agent (PoC for Nestbot) #1780 — Modifies RAG generator to use dynamic Prompt getters and touches related retrieval defaults; closely related to these changes.
  • Nestbot MVP #2113 — Updates Slack question detector to load its system prompt dynamically and add Prompt accessors; directly overlaps with Slack detector changes here.

Suggested labels

backend

Suggested reviewers

  • arkid15r
  • kasya

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The PR updates default constants for chunk retrieval limit and similarity threshold in backend/apps/ai/common/constants.py, which were not specified in issue #2406 and are unrelated to moving prompts or link formatting. Remove or separate the changes to DEFAULT_CHUNKS_RETRIEVAL_LIMIT and DEFAULT_SIMILARITY_THRESHOLD into a dedicated PR or justify their necessity in the linked issue.
Title Check ❓ Inconclusive The title hints at response enhancements and code refactoring but is too generic to convey specific changes such as dynamic prompts and link formatting. Consider refining the title to clearly reflect the key changes, for example “Move system prompts to Prompt model and format links in RAG response.”
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues Check ✅ Passed The changes remove hard-coded prompts and replace them with dynamic retrieval from the Prompt model for RAG and Slack question detection, thereby eliminating the need for OWASP-specific text; they migrate system prompts to the database model; and they introduce link formatting logic via format_links_for_slack, satisfying all three objectives of issue #2406.
Description Check ✅ Passed The description clearly references the linked issue and outlines the key changes made to improve RAG responses, migrate prompts to the model, and format links, which directly correspond to the diff.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link
Contributor

@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: 2

🧹 Nitpick comments (1)
backend/apps/slack/utils.py (1)

51-51: Optimize regex compilation.

The regex pattern is compiled on every function call. Moving it to a module-level constant would improve performance, especially if this function is called frequently.

Apply this diff to optimize:

+# Module-level constant for better performance
+_MARKDOWN_LINK_PATTERN = re.compile(r"\[([^\]]+)\]\((https?://[^\s)]+)\)")
+

 def format_links_for_slack(text: str) -> str:
     """Convert Markdown links to Slack markdown link format.
 
     Args:
         text (str): The input text that may include Markdown links.
 
     Returns:
         str: Text with Markdown links converted to Slack markdown links.
 
     """
     if not text:
         return text
 
-    markdown_link_pattern = re.compile(r"\[([^\]]+)\]\((https?://[^\s)]+)\)")
-    return markdown_link_pattern.sub(r"<\2|\1>", text)
+    return _MARKDOWN_LINK_PATTERN.sub(r"<\2|\1>", text)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 385ca51 and fd663e0.

📒 Files selected for processing (10)
  • backend/apps/ai/agent/tools/rag/generator.py (2 hunks)
  • backend/apps/ai/common/constants.py (1 hunks)
  • backend/apps/core/models/prompt.py (1 hunks)
  • backend/apps/slack/blocks.py (2 hunks)
  • backend/apps/slack/common/question_detector.py (2 hunks)
  • backend/apps/slack/utils.py (1 hunks)
  • backend/tests/apps/ai/agent/tools/rag/generator_test.py (5 hunks)
  • backend/tests/apps/ai/agent/tools/rag/rag_tool_test.py (2 hunks)
  • backend/tests/apps/ai/management/commands/ai_run_rag_tool_test.py (4 hunks)
  • backend/tests/apps/slack/common/question_detector_test.py (0 hunks)
💤 Files with no reviewable changes (1)
  • backend/tests/apps/slack/common/question_detector_test.py
🧰 Additional context used
🧬 Code graph analysis (6)
backend/apps/slack/blocks.py (2)
backend/apps/slack/utils.py (1)
  • format_links_for_slack (38-52)
backend/apps/slack/models/message.py (1)
  • text (83-85)
backend/apps/slack/common/question_detector.py (1)
backend/apps/core/models/prompt.py (2)
  • Prompt (14-161)
  • get_slack_question_detector_prompt (154-161)
backend/tests/apps/ai/agent/tools/rag/generator_test.py (1)
backend/apps/ai/agent/tools/rag/generator.py (2)
  • Generator (14-105)
  • generate_answer (61-105)
backend/apps/ai/agent/tools/rag/generator.py (1)
backend/apps/core/models/prompt.py (2)
  • Prompt (14-161)
  • get_rag_system_prompt (144-151)
backend/tests/apps/ai/agent/tools/rag/rag_tool_test.py (1)
backend/apps/ai/agent/tools/rag/rag_tool.py (1)
  • query (34-63)
backend/apps/slack/utils.py (1)
backend/apps/slack/models/message.py (1)
  • text (83-85)
⏰ 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). (3)
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests
🔇 Additional comments (10)
backend/apps/slack/blocks.py (2)

7-8: LGTM!

The import statement is clean and properly structured.


35-35: LGTM! Link formatting integration looks good.

The integration of format_links_for_slack ensures that Markdown links are properly converted to Slack's format before being rendered in blocks. This aligns with the PR objective to ensure website links are properly formatted.

backend/apps/slack/utils.py (1)

38-52: Handle URLs with parentheses and nested brackets
The pattern r"\[([^\]]+)\]\((https?://[^\s)]+)\)" stops at the first ) and won’t match URLs containing parentheses or link text with nested brackets (e.g. [Wiki](https://example.com/path(1)) or [Example [nested]](https://…)). If you need to support these cases, update the regex (e.g. balanced grouping or a more permissive pattern) and add tests covering them.

backend/tests/apps/ai/agent/tools/rag/rag_tool_test.py (1)

125-130: Defaults test coverage looks good

Thanks for updating both default-path assertions to the new limit=8 / threshold=0.1 values; this keeps the test suite aligned with the shared constants.

Also applies to: 153-158

backend/apps/ai/common/constants.py (1)

4-5: Updated retrieval defaults make sense

Bumping the retrieval limit to 8 and allowing similarity scores down to 0.1 matches the test adjustments and should help recall more context for RAG responses.

backend/tests/apps/ai/management/commands/ai_run_rag_tool_test.py (2)

43-43: LGTM! Comments accurately reflect the new defaults.

The inline comments correctly document the new constant values (DEFAULT_CHUNKS_RETRIEVAL_LIMIT=8 and DEFAULT_SIMILARITY_THRESHOLD=0.1).

Also applies to: 49-49


109-110: LGTM! Test values correctly updated to match new defaults.

All test cases now consistently use the new default values (limit=8, threshold=0.1), ensuring tests remain aligned with the updated constants.

Also applies to: 127-128, 139-141

backend/tests/apps/ai/agent/tools/rag/generator_test.py (3)

105-108: LGTM! Proper mocking of dynamic prompt retrieval.

All test methods that invoke generate_answer now correctly mock Prompt.get_rag_system_prompt, which is necessary since the production code dynamically retrieves the system prompt instead of using a hardcoded constant.

Also applies to: 135-138, 161-164, 182-185


202-225: LGTM! Comprehensive test for dynamic prompt integration.

The rewritten test effectively verifies:

  1. The system prompt is retrieved via Prompt.get_rag_system_prompt() (line 208-210)
  2. The retrieved prompt is correctly passed to OpenAI (lines 223-224)
  3. The getter is called exactly once (line 225)

This properly validates the refactoring from hardcoded prompts to dynamic retrieval.


230-230: LGTM! Constants test updated for refactored code.

The test correctly verifies only TEMPERATURE now, as SYSTEM_PROMPT has been removed in favor of dynamic prompt retrieval via Prompt.get_rag_system_prompt().

@arkid15r arkid15r marked this pull request as draft October 9, 2025 19:07
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
backend/tests/apps/slack/common/question_detector_test.py (1)

32-34: Consider removing unused parameter.

The monkeypatch parameter is not used in the fixture body. Since the autouse _mock_openai fixture already provides all necessary setup, this parameter is redundant.

Apply this diff:

     @pytest.fixture
-    def detector(self, monkeypatch):
+    def detector(self):
         """Fixture to provide QuestionDetector instance."""
         return QuestionDetector()
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd663e0 and b14409e.

📒 Files selected for processing (4)
  • backend/apps/ai/agent/tools/rag/generator.py (2 hunks)
  • backend/apps/slack/common/question_detector.py (2 hunks)
  • backend/tests/apps/ai/agent/tools/rag/generator_test.py (6 hunks)
  • backend/tests/apps/slack/common/question_detector_test.py (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • backend/apps/slack/common/question_detector.py
  • backend/apps/ai/agent/tools/rag/generator.py
  • backend/tests/apps/ai/agent/tools/rag/generator_test.py
🧰 Additional context used
🧬 Code graph analysis (1)
backend/tests/apps/slack/common/question_detector_test.py (1)
backend/apps/slack/common/question_detector.py (3)
  • QuestionDetector (18-136)
  • is_owasp_question_with_openai (82-125)
  • is_owasp_question (50-76)
⏰ 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). (4)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (4)
backend/tests/apps/slack/common/question_detector_test.py (4)

3-8: LGTM! Necessary imports for enhanced test coverage.

The new imports support comprehensive mocking, environment setup, and exception testing for the dynamic prompt retrieval and OpenAI integration.


16-29: LGTM! Solid test isolation strategy.

The autouse fixture prevents real OpenAI API calls during basic tests while allowing individual tests to override behavior with specific patches. The prompt mock aligns with the PR's goal to use dynamic prompt retrieval.


229-434: LGTM! Comprehensive test coverage for OpenAI integration.

The new tests thoroughly cover:

  • Missing/empty prompt validation (ObjectDoesNotExist)
  • All response scenarios (YES, NO, empty, None, unexpected)
  • API error handling
  • Case-insensitive response parsing

The isolated patching strategy in each test ensures proper test independence and aligns with the implementation in question_detector.py.


436-478: LGTM! Override logic is properly tested.

These tests verify the fallback behavior where keyword detection can override OpenAI's NO response, ensuring resilience when the AI model misclassifies OWASP-related questions. The patching strategy appropriately isolates the specific logic being tested.

@Dishant1804 Dishant1804 marked this pull request as ready for review October 10, 2025 18:01
@arkid15r arkid15r merged commit 28932a2 into OWASP:feature/nestbot-ai-assistant Oct 11, 2025
24 of 25 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Oct 18, 2025
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants