Skip to content
Draft
4 changes: 4 additions & 0 deletions deploy/ogx/test.containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ ENV PATH="/opt/app-root/.venv/bin:$PATH" \
# Set HOME directory so OGX uses /opt/app-root/src/.llama
ENV HOME="/opt/app-root/src"

# Point OGX at the external provider specs copied with the source tree above
# (e.g. remote::solr_vector_io for OKP RAG). Mirrors the production Containerfile.
ENV EXTERNAL_PROVIDERS_DIR="/opt/app-root/providers/resources/external_providers"

# Create python3 symlink for compatibility
RUN ln -sf /usr/bin/python3.12 /usr/bin/python3

Expand Down
125 changes: 123 additions & 2 deletions docs/devel_doc/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -16255,6 +16255,93 @@
"title": "OkpConfiguration",
"description": "OKP (Offline Knowledge Portal) provider configuration.\n\nControls provider-specific behaviour for the OKP vector store.\nOnly relevant when ``\"okp\"`` is listed in ``rag.retrieval.inline.sources``\nor ``rag.retrieval.tool.sources``."
},
"OkpFilter": {
"properties": {
"products": {
"items": {
"$ref": "#/components/schemas/OkpProductFilter"
},
"type": "array",
"title": "Products",
"description": "Product selections to include, OR'd together; each entry scopes its versions to its product.",
"examples": [
[
{
"product": "openshift_container_platform",
"versions": [
"4.16",
"4.17"
]
}
],
[
{
"product": "openshift_container_platform",
"versions": [
"4.16"
]
},
{
"product": "red_hat_enterprise_linux",
"versions": [
"9",
"10"
]
}
]
]
}
},
"additionalProperties": false,
"type": "object",
"title": "OkpFilter",
"description": "Transport-neutral, query-time OKP RAG filter.\n\nA domain-oriented product/version filter for the OKP RAG source,\ndeliberately decoupled from any backend filter vocabulary: it uses neither\nSolr's ``fq`` nor the OGX/llama-stack ``{type, key, value}`` grammar. Each\nOKP transport translates it into its own backend form (the RHOKP MCP\n``search`` tool args, or an OGX structured filter for the legacy Solr path),\nso the public interface is unaffected when OGX/Solr is retired.\n\nAttributes:\n products: Product selections to include, OR'd together. Each entry binds\n its versions to its product. An empty list applies no filter."
},
"OkpProductFilter": {
"properties": {
"product": {
"type": "string",
"title": "Product",
"description": "Exact product identifier (exact match, no wildcards).",
"examples": [
"openshift_container_platform",
"red_hat_enterprise_linux"
]
},
"versions": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"title": "Versions",
"description": "Exact versions of this product to include (exact match, no wildcards). When omitted, the product matches regardless of version.",
"examples": [
[
"4.16",
"4.17"
],
[
"9",
"10"
]
]
}
},
"additionalProperties": false,
"type": "object",
"required": [
"product"
],
"title": "OkpProductFilter",
"description": "A single product selection, with its versions scoped to that product.\n\nVersions live under their product so an invalid cross-pairing (e.g. a\nversion that belongs to a different product) is structurally\nunrepresentable. All values are matched exactly (no wildcards).\n\nAttributes:\n product: Exact product identifier to filter on (e.g.\n ``openshift_container_platform``).\n versions: Exact versions of this product to include. When None or empty,\n the product matches regardless of version."
},
"OpenAIResponseAnnotationCitation": {
"properties": {
"type": {
Expand Down Expand Up @@ -18953,6 +19040,30 @@
}
}
]
},
"okp": {
"anyOf": [
{
"$ref": "#/components/schemas/OkpFilter"
},
{
"type": "null"
}
],
"description": "Transport-neutral OKP RAG filter: exact-match product selections (each with its own versions) applied by whichever OKP transport is active (RHOKP MCP or the legacy Solr path).",
"examples": [
{
"products": [
{
"product": "openshift_container_platform",
"versions": [
"4.16",
"4.17"
]
}
]
}
]
}
},
"additionalProperties": false,
Expand All @@ -18961,7 +19072,7 @@
"query"
],
"title": "QueryRequest",
"description": "Model representing a request for the LLM (Language Model).\n\nAttributes:\n query: The query string.\n conversation_id: The optional conversation ID (UUID).\n provider: The optional provider.\n model: The optional model.\n system_prompt: The optional system prompt.\n attachments: The optional attachments.\n no_tools: Whether to bypass all tools and MCP servers (default: False).\n generate_topic_summary: Whether to generate topic summary for new conversations.\n media_type: The optional media type for response format (application/json or text/plain).\n vector_store_ids: The optional list of specific vector store IDs to query for RAG.\n shield_ids: The optional list of configured shield names to apply.\n solr: Optional Solr inline RAG options (mode, filters) or legacy filter-only dict.",
"description": "Model representing a request for the LLM (Language Model).\n\nAttributes:\n query: The query string.\n conversation_id: The optional conversation ID (UUID).\n provider: The optional provider.\n model: The optional model.\n system_prompt: The optional system prompt.\n attachments: The optional attachments.\n no_tools: Whether to bypass all tools and MCP servers (default: False).\n generate_topic_summary: Whether to generate topic summary for new conversations.\n media_type: The optional media type for response format (application/json or text/plain).\n vector_store_ids: The optional list of specific vector store IDs to query for RAG.\n shield_ids: The optional list of configured shield names to apply.\n solr: Optional Solr inline RAG options (mode, filters) or legacy filter-only dict.\n okp: Optional transport-neutral OKP RAG filter (product, product_version).",
"examples": [
{
"attachments": [
Expand Down Expand Up @@ -20398,6 +20509,16 @@
"type": "null"
}
]
},
"okp": {
"anyOf": [
{
"$ref": "#/components/schemas/OkpFilter"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
Expand All @@ -20406,7 +20527,7 @@
"input"
],
"title": "ResponsesRequest",
"description": "Model representing a request for the Responses API following LCORE specification.\n\nAttributes:\n input: Input text or structured input items containing the query.\n model: Model identifier in format \"provider/model\". Auto-selected if not provided.\n conversation: Conversation ID linking to an existing conversation. Accepts both\n OpenAI and LCORE formats. Mutually exclusive with previous_response_id.\n include: Explicitly specify output item types that are excluded by default but\n should be included in the response.\n instructions: System instructions or guidelines provided to the model (acts as\n the system prompt).\n max_infer_iters: Maximum number of inference iterations the model can perform.\n max_output_tokens: Maximum number of tokens allowed in the response.\n max_tool_calls: Maximum number of tool calls allowed in a single response.\n metadata: Custom metadata dictionary with key-value pairs for tracking or logging.\n parallel_tool_calls: Whether the model can make multiple tool calls in parallel.\n previous_response_id: Identifier of the previous response in a multi-turn\n conversation. Mutually exclusive with conversation.\n prompt: Prompt object containing a template with variables for dynamic\n substitution.\n reasoning: Reasoning configuration for the response.\n safety_identifier: Safety identifier for the response.\n store: Whether to store the response in conversation history. Defaults to True.\n stream: Whether to stream the response as it is generated. Defaults to False.\n temperature: Sampling temperature controlling randomness (typically 0.0\u20132.0).\n text: Text response configuration specifying output format constraints (JSON\n schema, JSON object, or plain text).\n tool_choice: Tool selection strategy (\"auto\", \"required\", \"none\", or specific\n tool configuration).\n tools: List of tools available to the model (file search, web search, function\n calls, MCP tools). Defaults to all tools available to the model.\n generate_topic_summary: LCORE-specific flag indicating whether to generate a\n topic summary for new conversations. Defaults to True.\n shield_ids: LCORE-specific list of configured shield names to apply.\n If None, all configured shields are used.\n solr: Optional Solr inline RAG options (mode, filters) or legacy filter-only dict.",
"description": "Model representing a request for the Responses API following LCORE specification.\n\nAttributes:\n input: Input text or structured input items containing the query.\n model: Model identifier in format \"provider/model\". Auto-selected if not provided.\n conversation: Conversation ID linking to an existing conversation. Accepts both\n OpenAI and LCORE formats. Mutually exclusive with previous_response_id.\n include: Explicitly specify output item types that are excluded by default but\n should be included in the response.\n instructions: System instructions or guidelines provided to the model (acts as\n the system prompt).\n max_infer_iters: Maximum number of inference iterations the model can perform.\n max_output_tokens: Maximum number of tokens allowed in the response.\n max_tool_calls: Maximum number of tool calls allowed in a single response.\n metadata: Custom metadata dictionary with key-value pairs for tracking or logging.\n parallel_tool_calls: Whether the model can make multiple tool calls in parallel.\n previous_response_id: Identifier of the previous response in a multi-turn\n conversation. Mutually exclusive with conversation.\n prompt: Prompt object containing a template with variables for dynamic\n substitution.\n reasoning: Reasoning configuration for the response.\n safety_identifier: Safety identifier for the response.\n store: Whether to store the response in conversation history. Defaults to True.\n stream: Whether to stream the response as it is generated. Defaults to False.\n temperature: Sampling temperature controlling randomness (typically 0.0\u20132.0).\n text: Text response configuration specifying output format constraints (JSON\n schema, JSON object, or plain text).\n tool_choice: Tool selection strategy (\"auto\", \"required\", \"none\", or specific\n tool configuration).\n tools: List of tools available to the model (file search, web search, function\n calls, MCP tools). Defaults to all tools available to the model.\n generate_topic_summary: LCORE-specific flag indicating whether to generate a\n topic summary for new conversations. Defaults to True.\n shield_ids: LCORE-specific list of configured shield names to apply.\n If None, all configured shields are used.\n solr: Optional Solr inline RAG options (mode, filters) or legacy filter-only dict.\n okp: Optional transport-neutral OKP RAG filter (product selections with versions).",
"examples": [
{
"generate_topic_summary": true,
Expand Down
25 changes: 25 additions & 0 deletions docs/user_doc/rag_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,31 @@ Example:
}
```

The `solr` field and its `fq`/structured filters are Solr-specific. For a
backend-neutral, forward-compatible product/version filter that works across
**both** OKP transports (the RHOKP MCP server and the legacy Solr path), use the
request field **`okp`** instead. It carries a list of product selections, each
scoping its own exact-match versions (no wildcards), so an invalid
product/version pairing is not representable. Product/version filtering is
query-time only; there is no launch-time product/version configuration.

```json
{
"query": "How do I configure routes?",
"okp": {
"products": [
{ "product": "openshift_container_platform", "versions": ["4.16", "4.17"] }
]
}
}
```

Multiple products are OR'd; a product with no `versions` matches regardless of
version. On the MCP transport each (product, version) pair becomes one search and
the results are merged, deduplicated, and capped at `rag.okp.max_chunks`. Prefer
`okp` over `solr` for product/version filtering; `solr` remains for Solr-specific
needs during the OGX/Solr transition.

**Prerequisites:**

- The OKP server must be running and accessible at the URL given in `rag.okp.rhokp_url` (or `${env.RH_SERVER_OKP}`).
Expand Down
1 change: 1 addition & 0 deletions src/app/endpoints/a2a.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ async def _process_task_streaming( # pylint: disable=too-many-locals
),
shield_ids=None,
solr=None,
okp=None,
)

# Get LLM client and select model
Expand Down
1 change: 1 addition & 0 deletions src/app/endpoints/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ async def _handle_query_with_tracing(
query_request.query,
query_request.vector_store_ids,
query_request.solr,
query_request.okp,
)

# Prepare API request parameters
Expand Down
1 change: 1 addition & 0 deletions src/app/endpoints/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ async def handle_responses_with_tracing( # pylint: disable=too-many-locals
input_text,
vector_store_ids,
original_request.solr,
original_request.okp,
)
if moderation_result.decision == "passed":
updated_request.input = append_inline_rag_context_to_responses_input(
Expand Down
1 change: 1 addition & 0 deletions src/app/endpoints/streaming_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ async def _handle_streaming_query_with_tracing( # pylint: disable=too-many-loca
query_request.query,
query_request.vector_store_ids,
query_request.solr,
query_request.okp,
)

# Prepare API request parameters
Expand Down
Loading
Loading