Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions application/single_app/admin_settings_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,55 @@
},
"group": {"id": "connection", "label": "Connection", "variant": "connection"},
},
# Declared here because the fallback scan matched "search" and filed the

Check warning on line 1096 in application/single_app/admin_settings_fields.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
# switch under Web Search, which reaches the public internet. This cache sits

Check warning on line 1097 in application/single_app/admin_settings_fields.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
# in front of the workspace indexes configured above.
{
"key": "enable_search_result_caching",

Check warning on line 1100 in application/single_app/admin_settings_fields.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
"type": "switch",
"label": "Cache workspace search results",

Check warning on line 1102 in application/single_app/admin_settings_fields.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
"help": (
"Reuses the results of a recent identical search, so a repeated question "

Check warning on line 1104 in application/single_app/admin_settings_fields.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
"returns faster, cites the same sources, and skips the query embedding and "

Check warning on line 1105 in application/single_app/admin_settings_fields.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.

Check warning on line 1105 in application/single_app/admin_settings_fields.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains security control, sanitization, or audit marker. Recommendation%3A Confirm the change does not weaken auth, CSRF, CSP, XSS defenses, settings sanitization, redaction, audit logging, or tests.
"the semantic-ranked Azure AI Search queries. Results are reused only while "

Check warning on line 1106 in application/single_app/admin_settings_fields.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
"the query, scope, filters, embedding model and the documents in scope, "

Check warning on line 1107 in application/single_app/admin_settings_fields.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
"including their versions, still match, and they are re-checked against the "
"requesting user's access before they are returned. Leave it on; turn it off "
"only to make every search run fresh while you troubleshoot relevance."

Check warning on line 1110 in application/single_app/admin_settings_fields.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
),
"default": True,
"group": {
"id": "search-result-cache",
"label": "Search result cache",
"variant": "behavior",
"help": (
"Applies to the workspace document searches behind grounded chat, "
"agents and workflows, not to web search. Cached results are kept in "
"the search_cache Cosmos DB container, so Redis is not required."
),
},
},
{
"key": "search_cache_ttl_seconds",
"type": "number",
"label": "Cache lifetime (seconds)",
"help": (
"How long a cached result set can be reused. Adding, deleting, re-sharing "
"or re-versioning a document forces a fresh search straight away. Other "
"changes, such as a document that finishes processing after the search ran "
"or an edit made directly in Azure AI Search, can take up to this long to "
"appear. 300 seconds (5 minutes) by default."
),
"default": 300,
"min": 60,
"max": 3600,
"group": {
"id": "search-result-cache",
"label": "Search result cache",
"variant": "behavior",
},
"depends_on": {"key": "enable_search_result_caching", "equals": True},
},
],
# ------------------------------------------------------------------
# Knowledge / Web & Research
Expand Down Expand Up @@ -6241,6 +6290,17 @@
"Same as enable_app_maintenance: no server-rendered control, and misfiled "
"into Security by the fallback scan until it was declared."
),
"enable_search_result_caching": (
"The classic Azure AI Search card showed this switch briefly in late 2025, "
"but the classic save handler never stored it and the control was removed. "
"Declared under Azure AI Search so the fallback scan stops filing it under "
"Web Search, which it matched on the shared word stem 'search'."
),
"search_cache_ttl_seconds": (
"Read by utils_cache.get_cache_settings() but editable in neither interface "
"since the classic control was removed alongside the caching switch. "
"Declared with that switch so the cache lifetime can be tuned."
),
}


Expand Down
2 changes: 1 addition & 1 deletion application/single_app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
EXECUTOR_TYPE = 'thread'
EXECUTOR_MAX_WORKERS = 30
SESSION_TYPE = 'filesystem'
VERSION = "0.261.262"
VERSION = "0.261.263"
IS_DEVELOPMENT = is_development_env_enabled()

# Opt-out for deployments where App Service Easy Auth is active but the platform
Expand Down
2 changes: 1 addition & 1 deletion docs/admin/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,6 @@ This layout was implemented in **0.261.258**.
| Governance | Governance controls review policy for personal, group, and global endpoints, agents, actions, and MCP destinations. | `feature-governance`, `governance-policies`, `mcp-governance` | [Governance settings]({{ '/admin/governance/' | relative_url }}) |
| Data Lifecycle | Data Lifecycle groups retention, classification, and conversation archiving decisions. | `retention`, `classification`, `archiving` | [Data Lifecycle settings]({{ '/admin/data-lifecycle/' | relative_url }}) |
| Backup & Recovery | Backup & Recovery contains backup readiness, scheduled backups, migration, restore, backup inventory, job history, and Cosmos JSON repair tools. | `backup`, `migrate`, `restore`, `cosmos-editor`, `jobs` | [Backup & Recovery settings]({{ '/admin/backup-recovery/' | relative_url }}) |
| Scale | Scale covers Redis, conversation and search caches, document access indexing, Cosmos maintenance, and Cosmos throughput automation. | `redis-caching`, `cosmos` | [Scale settings]({{ '/admin/scale/' | relative_url }}) |
| Scale | Scale covers Redis, the conversation and document list caches, document access indexing, Cosmos maintenance, and Cosmos throughput automation. | `redis-caching`, `cosmos` | [Scale settings]({{ '/admin/scale/' | relative_url }}) |
| Operations | Operations collects Control Center access, refresh behavior, Application Insights, debug logging, file-processing logs, health checks, and Swagger documentation. | `control-center-config`, `logging` | [Operations settings]({{ '/admin/operations/' | relative_url }}) |
| Help | Help controls end-user support navigation, Send Feedback destinations, and Latest Features cards. | `support-menu`, `send-feedback`, `latest-features` | [Help settings]({{ '/admin/help/' | relative_url }}) |
13 changes: 13 additions & 0 deletions docs/admin/knowledge.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ In the classic interface, opening Admin Settings checks the three indexes in seq

Connection and permission failures stay visible rather than being hidden as if the index were healthy. Configure either the direct Search endpoint and authentication method, or the APIM endpoint and subscription key. Public Azure uses the Search audience `https://search.azure.com`; government and custom-cloud audiences remain separate. See [Admin settings troubleshooting]({{ '/troubleshooting/#admin-settings-saves-and-connection-tests' | relative_url }}).

#### Search result cache

Workspace document searches, the retrieval step behind grounded chat answers, agents, and workflows, are cached in the `search_cache` Cosmos DB container. When the same search runs again against the same documents, SimpleChat reuses the earlier results instead of embedding the query and running the semantic-ranked hybrid queries against each workspace index again. Repeated questions come back faster and cite the same sources, and fewer embedding and semantic ranker requests are billed or counted against quota. The cache does not need Redis, and it does not apply to web search.

A cached result is reused only while the query, scope, selected documents, tag filters, embedding model, and the documents in scope, including their versions and content screening state, all still match. Adding, deleting, re-sharing, or re-versioning a document therefore forces a fresh search straight away. Before cached results are returned, each one is re-checked against the requesting user's access and the document's current availability, and if any no longer qualifies the search runs fresh.

Caching is on by default and should stay on. Turn it off only while troubleshooting search relevance, when every search needs to run fresh. The cache lifetime bounds how long other changes can take to appear, such as a document that finishes processing after a search ran, or an edit made directly in Azure AI Search outside SimpleChat.

Both settings are edited in the V2 admin settings, in the **Search result cache** group of this section. The classic admin page has no control for them.

#### Settings

| Setting | What it does | Default | Notes |
Expand All @@ -117,6 +127,8 @@ Connection and permission failures stay visible rather than being hidden as if t
| Search Key | Provides the secret credential used when the selected authentication mode requires one. | Empty | `azure_ai_search_key` |
| Azure APIM AI Search Endpoint | Provides the endpoint or route SimpleChat uses for this service. | Empty | `azure_apim_ai_search_endpoint` |
| Azure APIM AI Search Subscription Key | Provides the secret credential used when the selected authentication mode requires one. | Empty | `azure_apim_ai_search_subscription_key` |
| Cache workspace search results | Reuses a recent identical workspace search instead of embedding the query and querying the indexes again. Cached results are re-checked against the user's access before they are returned. | On | `enable_search_result_caching`; V2 admin only |
| Cache lifetime (seconds) | How long cached results can be reused, from 60 to 3,600 seconds. Shown while caching is on. | 300 | `search_cache_ttl_seconds`; V2 admin only |

## Document Extraction {#extraction}

Expand Down Expand Up @@ -426,6 +438,7 @@ The Public Workspace Sync section belongs to the File Sync tab. Use it with the
| Symptom | Likely cause | Fix |
| --- | --- | --- |
| A synced file is not searchable | The source ran but extraction or indexing failed later. | Check sync state, extraction settings, and Azure AI Search before rerunning. |
| A repeated question still returns the old sources after a change made directly in Azure AI Search | The search result cache is reusing results from before the change, which it cannot detect. | Wait for the cache lifetime to pass. To check the change sooner, rephrase the question, because different wording is a separate cache entry. |

## Related

Expand Down
7 changes: 4 additions & 3 deletions docs/admin/scale.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
layout: page
title: "Scale settings"
description: "Scale covers Redis, conversation and search caches, document access indexing, Cosmos maintenance, and Cosmos throughput automation."
description: "Scale covers Redis, the conversation and document list caches, document access indexing, Cosmos maintenance, and Cosmos throughput automation."
section: "Administration"
audience: admin
admin_tab: scale
Expand All @@ -12,7 +12,7 @@ admin_tab: scale

## What this group controls

Scale covers Redis, conversation and search caches, document access indexing, Cosmos maintenance, and Cosmos throughput automation.
Scale covers Redis, the conversation and document list caches, document access indexing, Cosmos maintenance, and Cosmos throughput automation.

## Why it matters

Expand All @@ -30,6 +30,8 @@ Scale settings trade latency, freshness, and Azure spend. Caches can make the ap

## Redis & Caching {#redis-caching}

The workspace search result cache is not configured here. It is part of Azure AI Search on the [Knowledge settings]({{ '/admin/knowledge/#azure-ai-search-section' | relative_url }}) page, and it is stored in Cosmos DB rather than Redis.

### Redis Cache {#redis-cache-section}

SimpleChat connects to either Azure Managed Redis or Azure Cache for Redis. The two services
Expand Down Expand Up @@ -156,7 +158,6 @@ The Cosmos Metrics section belongs to the Cosmos tab. Use it with the adjacent s
| --- | --- | --- | --- |
| Key Filter | Blank filter browses all keys. Filters are case sensitive. Redis SCAN order is server-defined, so use Next Page to keep browsing. | N/A (runtime control) | Runtime UI control |
| Page Size | Defines behavior for the related admin workflow; verify the affected feature after saving. | Not specified in defaults | Runtime UI control |
| Search result caching | Caches workspace search-result payloads with document-set fingerprints so repeated personal, group, public, or all-scope searches can reuse results until document changes or the TTL invalidate them. | On | `enable_search_result_caching`; no visible field in `admin_settings.html` |
| Write-through projection | Exposes the capability after required services, permissions, and rollout policy are ready. | On | `enable_document_access_index_write_through`; capability toggle |
| Automatic repair/backfill | Exposes the capability after required services, permissions, and rollout policy are ready. | On | `enable_startup_document_access_index_backfill`; capability toggle |
| Enable shadow validation | Exposes the capability after required services, permissions, and rollout policy are ready. | Off | `enable_document_access_index_shadow_validation`; capability toggle |
Expand Down
8 changes: 8 additions & 0 deletions docs/explanation/features/V2_ADMIN_KNOWLEDGE_SETTINGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ that the two interfaces order or group them identically. The intentional differe
`get_source_review_config` rewrites any other value on read.
- The Video Indexer cloud selector not reproduced. It has no stored setting of its own,
existing only to compute `video_indexer_endpoint`, which V2 edits directly.
- The search result cache is V2-only. Added in **0.261.263**, `enable_search_result_caching`
and `search_cache_ttl_seconds` form a **Search result cache** group after the Azure AI
Search connection, with an explanation of what is cached, what forces a fresh search, and
why to leave it on. The classic page dropped its short-lived control, which never saved,
in late 2025. Until the switch was declared, the fallback scan matched "search" and filed
it under Web Search as a bare toggle. Both keys are recorded in `V2_ONLY_FIELDS`.

## Testing

Expand All @@ -151,6 +157,8 @@ that the two interfaces order or group them identically. The intentional differe
| `test_v2_admin_knowledge_extraction.py` | Parity, connection-first ordering, chunk size storage |
| `test_v2_admin_knowledge_audio_video.py` | Parity, audio cue relocation, shared Speech disclosure |
| `test_v2_admin_knowledge_file_sync.py` | Parity, Redis prerequisite, GB/bytes conversion, assignments |
| `test_search_result_cache_admin_setting.py` | Search result cache placement, defaults against the runtime, lifetime bounds, V2-only record |
| `ui_tests/test_v2_admin_search_result_cache.py` | The cache group renders under Azure AI Search, hides its lifetime while off, and saves through the normalizer |
| `test_model_vision_capability_resolution.py` | Three-tier resolution and its precedence |

## Known limitations
Expand Down
105 changes: 105 additions & 0 deletions docs/explanation/fixes/SEARCH_RESULT_CACHE_ADMIN_SETTING_FIX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Search Result Cache Admin Setting Fix

## Issue

V2 Admin Settings showed **Search result caching** as a bare switch under
**Knowledge › Web & Research › Web Search**. It had no description, only the label built
from its key and the raw key `enable_search_result_caching`. Administrators could not tell
what it cached, whether it should be on, or why it sat beside a setting that sends messages
to the public internet. The cache's lifetime, `search_cache_ttl_seconds`, had no control in
either admin interface.

## Root cause

The key had no field in `admin_settings_fields.py`, so the V2 surface found it through its
`enable_*` fallback scan (`buildCapabilityIndex` in `AdminSettingsPage.tsx`). That scan files
a key under the section whose id shares the most word stems with it. "search" scored one
point in both `web-search-section` and `azure-ai-search-section`. Web Search comes first in
navigation order and the first section to reach the top score keeps it, so the cache landed
in Web Search. A switch found that way can only show the key's name.

The setting caches workspace document searches against Azure AI Search, not web search. The
classic Azure AI Search card briefly offered both controls in late 2025, but the classic save
handler never stored them and they were removed, so neither key has had a working control
since.

## Fixed in version: **0.261.263**

The application version is maintained in `application/single_app/config.py`.

## Technical details

### Files modified

| File | Change |
| --- | --- |
| `application/single_app/admin_settings_fields.py` | Declares both settings in a **Search result cache** group of `azure-ai-search-section`, and records them in `V2_ONLY_FIELDS`. |
| `application/single_app/config.py` | Version 0.261.263. |
| `functional_tests/test_v2_admin_capability_placement.py` | Pins the relocation in `RELOCATED_CAPABILITIES_WITHOUT_V1_FIELD`. |
| `functional_tests/test_search_result_cache_admin_setting.py` | New. |
| `ui_tests/test_v2_admin_search_result_cache.py` | New. |
| `docs/admin/knowledge.md`, `docs/admin/scale.md`, `docs/admin/index.md` | Explain the cache with Azure AI Search, and remove the row that described it under Scale. |

### Code changes

- **Cache workspace search results** (`enable_search_result_caching`, switch, default on)
explains that a repeated identical search reuses the earlier results and skips the query
embedding and the semantic-ranked Azure AI Search queries. It also says what has to match
for a cached result to be reused, that cached results are re-checked against the
requesting user's access, and that the only reason to turn it off is to force fresh
searches while troubleshooting relevance.
- **Cache lifetime (seconds)** (`search_cache_ttl_seconds`, default 300, 60 to 3,600) is
shown only while caching is on. Saves are clamped to that range by the existing number
normalizer.
- The group follows the Connection group, so the section still leads with its endpoint and
credentials. Its description says the cache covers the searches behind grounded chat,
agents and workflows, not web search, and that it uses Cosmos DB rather than Redis.
- Declaring the key takes it out of the fallback scan, so the Web Search row is gone.

### Default

No default changed. Caching has defaulted to on since it was introduced, in both
`functions_settings.py` and the fallback in `utils_cache.get_cache_settings()`, and it should
stay on:

- A cache hit saves an embedding call and one semantic-ranked hybrid query per workspace
index in scope, and the semantic ranker is billed and quota-limited per query.
- A hit returns the same sources for the same question. The semantic ranker alone does not
guarantee that.
- It is safe to reuse: the cache key includes the documents in scope with their versions and
content screening state, and every cached result is re-authorized for the requesting user
before it is returned.

A value an administrator explicitly saved as off is left as is.

## Validation

- `functional_tests/test_search_result_cache_admin_setting.py` checks placement and field
order, the labels and explanations, the lifetime's bounds and visibility, that the schema
defaults match `functions_settings.py` and `utils_cache.py`, PATCH clamping, and that no
classic form submits either key.
- `functional_tests/test_v2_admin_capability_placement.py` fails if the switch is undeclared
and falls back to the stem-matched guess.
- `ui_tests/test_v2_admin_search_result_cache.py` renders the built V2 page with the real
schema. It checks that the group explains the cache with the switch on and the lifetime at
300, that the Web Search card shows nothing of the old row, that turning caching off hides
the lifetime and saves `false`, and that a lifetime of 5 saves as 60.

Before: a key-named switch under Web Search, and no way to change the lifetime. After: an
explained **Search result cache** group inside Azure AI Search, with the lifetime beside it.

## Known follow-ups

These existed before this change and were not altered by it:

- `invalidate_group_search_cache` and `invalidate_public_workspace_search_cache` filter on
`CONTAINS(c.doc_scope, <id>)`, but `doc_scope` stores only the scope name. Unless the group
call passes `document_id`, they delete nothing. Document fingerprints still keep cached
results correct, so the cache lifetime is what bounds changes that do not alter a
document's version.
- The `search_cache` container has no Cosmos TTL. Expired entries are deleted only when the
same search is read again or a personal invalidation runs, so entries for searches that are
never repeated accumulate.

Related: [Knowledge Settings in the V2 Admin Surface](../features/V2_ADMIN_KNOWLEDGE_SETTINGS.md),
[Search Result Caching](../features/v0.235.001/SEARCH_RESULT_CACHING.md).
Loading
Loading