Skip to content

MAIT-205: Replace ROAT Filter Function with OWUI Workspace Tool#48

Open
acikabubo wants to merge 2 commits intomainfrom
MAIT-205-rework-roat-retrieval-function-into-a-tool
Open

MAIT-205: Replace ROAT Filter Function with OWUI Workspace Tool#48
acikabubo wants to merge 2 commits intomainfrom
MAIT-205-rework-roat-retrieval-function-into-a-tool

Conversation

@acikabubo
Copy link
Copy Markdown
Contributor

Summary

  • Add tools/roat_retrieval.py — OWUI Workspace Tool that queries ROAT only when the LLM decides it's relevant, replacing the Filter that ran on every message
  • Disable functions/function.py by default (enabled: false + env default changed to false) to prevent double context injection
  • Update README with Tool activation instructions

Add tools/roat_retrieval.py — a Workspace Tool that queries the ROAT
knowledge base on-demand, letting the LLM decide when retrieval is
needed instead of running on every user message.

Disable functions/function.py by default (enabled: false header +
ENABLE_CUSTOM_RAG_SERVICE env default changed to false) to prevent
double context injection when the tool is active. Also apply minor
linter fixes to the filter file (import order, type hint syntax).

Update README to replace the filter setup blurb with step-by-step
Tool activation instructions (import, valves, model config, function
calling mode, per-chat activation).
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

Warning

Rate limit exceeded

@acikabubo has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 46 minutes before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bc937f8a-2d15-4703-a869-f2b95ad1cc02

📥 Commits

Reviewing files that changed from the base of the PR and between a4234d2 and 07350ec.

📒 Files selected for processing (1)
  • tools/roat_retrieval.py
📝 Walkthrough

Walkthrough

The changes migrate RAG integration from a legacy custom filter function to a new workspace tool-based retrieval mechanism. The legacy filter is disabled by default, the README documents explicit ROAT tool activation steps, and a new tools/roat_retrieval.py module implements ROAT knowledge base querying with HTTP API integration and response formatting.

Changes

Cohort / File(s) Summary
Documentation
README.md
Updated RAG integration instructions to reflect new ROAT tool-based retrieval workflow, including activation steps, configuration requirements, and explicit warning that legacy filter is disabled.
Legacy Filter
functions/function.py
Disabled custom RAG service by default via ENABLE_CUSTOM_RAG_SERVICE flag; modernized type annotations from typing to collections.abc and Python 3.10+ union syntax; refactored expressions for conciseness.
ROAT Retrieval Tool
tools/roat_retrieval.py
New module implementing workspace tool for ROAT knowledge base queries; includes Tools class with configurable Valves (service URL, API key, timeout, top-k), async search_knowledge_base method that calls ROAT HTTP API with optional Bearer auth, and response formatting into markdown context with source metadata and per-source event emission.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Tools as Tools.search_knowledge_base
    participant ROAT as ROAT API Endpoint
    participant Formatter as Response Formatter

    Client->>Tools: search_knowledge_base(query)
    Tools->>Tools: Validate rag_service_url config
    Tools->>Tools: Emit progress event
    Tools->>ROAT: POST /query (JSON: query, top_k, metadata_filters)
    ROAT-->>Tools: HTTP 200 + relevance chunks
    Tools->>Formatter: Parse chunks into {score, text}
    Tools->>Formatter: Extract filenames & source metadata
    Tools->>Tools: Emit per-source status events
    Formatter-->>Tools: Formatted markdown context + sources
    Tools-->>Client: Combined context string
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% 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
Title check ✅ Passed The title accurately describes the main change: replacing a Filter function with a Workspace Tool for ROAT retrieval, which aligns with the PR's primary objective.
Description check ✅ Passed The description is directly related to the changeset, outlining the three key modifications: adding the new tool, disabling the filter, and updating documentation.
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.


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
Review rate limit: 0/1 reviews remaining, refill in 46 minutes.

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

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

🧹 Nitpick comments (1)
functions/function.py (1)

135-136: ⚡ Quick win

Align get_filename_from_extras return type with actual behavior.

At Line 136, the function can return None, but it is annotated as str. Please update the annotation to avoid incorrect type assumptions.

Suggested diff
-def get_filename_from_extras(self, extras: dict) -> str:
+def get_filename_from_extras(self, extras: dict) -> str | None:
     return extras.get("key") or extras.get("filename") or extras.get("name") or None
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@functions/function.py` around lines 135 - 136, The get_filename_from_extras
function is annotated to return str but can return None; update its signature to
return Optional[str] (import Optional from typing) so the type matches behavior
and adjust any callers if they assume a non-None return; reference the
get_filename_from_extras method to locate where to change the annotation and add
the necessary import.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tools/roat_retrieval.py`:
- Around line 59-60: Normalize the extras variable to always be a dict by
replacing extras = ref.get("extras", {}) with extras = ref.get("extras") or {}
so None becomes {} and cannot raise AttributeError; then update any subsequent
usage sites that call extras.items() or extras.get() (e.g., the
metadata.extend(...) and extras.get(...) usages) to rely on this normalized dict
and remove protective checks, ensuring functions/methods that process "extras"
(the local extras variable and the metadata handling logic) operate safely.
- Line 40: Current logging call log.info("Calling ROAT for query: %s",
query[:80]) exposes raw user input; change it to log only metadata such as the
query length and a request or correlation id (e.g., use len(query) and
request_id/correlation_id if available) and remove the query content. Replace
the format string to something like "Calling ROAT: query_length=%d
request_id=%s" and pass len(query) and the existing request id (or generate one
earlier in the request handling code) so no PII is written to logs while
retaining traceability.
- Around line 137-183: The async method search_knowledge_base calls the blocking
synchronous helper _call_rag_service (which uses requests.post) and thus blocks
the event loop; fix this by invoking _call_rag_service inside asyncio.to_thread
and awaiting it (e.g., rag_result = await asyncio.to_thread(_call_rag_service,
self.valves.rag_service_url, self.valves.rag_service_api_key,
self.valves.rag_service_timeout, self.valves.top_k, query)), and ensure asyncio
is imported; keep the existing emit/error handling and return behavior
unchanged.

---

Nitpick comments:
In `@functions/function.py`:
- Around line 135-136: The get_filename_from_extras function is annotated to
return str but can return None; update its signature to return Optional[str]
(import Optional from typing) so the type matches behavior and adjust any
callers if they assume a non-None return; reference the get_filename_from_extras
method to locate where to change the annotation and add the necessary import.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1dc34ad5-fbd6-4f01-a368-70b3f6b0273a

📥 Commits

Reviewing files that changed from the base of the PR and between afe51ff and a4234d2.

📒 Files selected for processing (3)
  • README.md
  • functions/function.py
  • tools/roat_retrieval.py

Comment thread tools/roat_retrieval.py Outdated
Comment thread tools/roat_retrieval.py Outdated
Comment thread tools/roat_retrieval.py
- Normalize extras to dict safely with `or {}` to handle explicit null
- Remove query content from logs, log query length only
- Run blocking requests.post in asyncio.to_thread to avoid blocking the event loop
Comment thread functions/function.py
# Read configuration from environment variables
DEFAULT_ENABLED = os.getenv("ENABLE_CUSTOM_RAG_SERVICE", "true").lower() == "true"
# Disabled by default — retrieval has moved to the ROAT Knowledge Base Search workspace tool (tools/roat_retrieval.py)
DEFAULT_ENABLED = os.getenv("ENABLE_CUSTOM_RAG_SERVICE", "false").lower() == "true"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We can keep other improvements made to this function code, but let's please revert the change that changes the DEFAULT_ENABLED. The state of the filter function is to be controlled via the OWUI interface, not via Valve's defaults

Comment thread README.md

The filter function that's responsible for the RAG service communication will also be
automatically provisioned and enabled globally. You can change these settings at the Admin panel
The filter function that was previously responsible for RAG service communication has been replaced
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this fits more to be included in a changelog (what we don't yet have) rather than in a README. Let's instead simply ensure both the Filter function and the Tool are documented

Comment thread README.md

### Activating the ROAT Tool

After first boot, manually register the tool:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Moving forward, we're going to remove the code that automatically enables the Filter function and replace it with the code that automatically enables the Tool instead. So these instructions on manual activation should be unnecessary

Comment thread tools/roat_retrieval.py
Use this tool when:
- The user asks a factual question that likely requires domain-specific knowledge
- The user asks about documented processes, policies, data, or internal content
- The user's question cannot be confidently answered from general training knowledge alone
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In fact, we want this tool used for most of the queries, and we want to disincentivize the LLM from using general knowledge. Thus, I propose to drop this line and instead replace it with something that would instruct the model to use this tool more frequently

We're of course just guessing for now until we have some evaluations in place

Comment thread tools/roat_retrieval.py
Do NOT use this tool for:
- Casual greetings or small talk
- Simple arithmetic or general world knowledge
- Follow-up questions within an ongoing conversation where context was already retrieved
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think this specific instruction as follow up questions may require queries into the ROAT, let's try to reformulate this

Comment thread tools/roat_retrieval.py
query: A concise search query derived from the user's question

Returns:
Retrieved context passages from the knowledge base, or a message that nothing was found.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please reword into Retrieved documents chunks and their metadata.....

Comment thread tools/roat_retrieval.py

source_obj = {
"source": {"name": source_name},
"document": [text[:1000] if len(text) > 1000 else text],
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

While we're at it, can we please make this configurable via Valve, making it unlimited by default?

Comment thread tools/roat_retrieval.py
{
"source": source_name,
"file": filename,
"relevance_score": score,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not something new - it was like that in the Filter function, but I noticed that the relevance_score is not displayed by the OWUI when viewing the citation source. Do you have any ideas why?

Comment thread tools/roat_retrieval.py
@@ -0,0 +1,203 @@
"""
title: ROAT Knowledge Base Search
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please rename this to just the "Knowledge Base Search"

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