Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

188 changes: 188 additions & 0 deletions docs/ai/design/feature-mobile-rag-retrieval-tuning-ui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
---
phase: design
title: Mobile RAG Retrieval Tuning UI
description: Architecture for bringing persisted retrieval settings and precision tuning to mobile AI search
---

# System Design & Architecture

## Architecture Overview
**What is the high-level system structure?**

```mermaid
graph TD
subgraph Mobile UI
Settings["Settings screen / API Keys panel"]
Search["Search screen"]
Slider["Precision slider"]
MobileMode["useMobileSearchMode"]
MobileHook["useMobileAIPaginatedSearch"]
end

subgraph Shared Core
SearchSettings["ragSearchSettings defaults/validation"]
SearchService["RagSearchSettingsService"]
ApiKeys["ApiKeysSettingsService"]
end

subgraph Supabase Edge Functions
Status["api-keys-status"]
Upsert["api-keys-upsert"]
RagSearch["rag-search"]
end

subgraph Database
SearchSettingsTable[("user_rag_search_settings")]
Embeddings[("note_embeddings")]
end

Settings --> SearchService
Settings --> ApiKeys
Search --> MobileMode
Search --> Slider
Slider --> SearchService
Search --> MobileHook
MobileHook --> SearchService
MobileHook --> RagSearch
SearchService --> Status
SearchService --> Upsert
Status --> SearchSettingsTable
Upsert --> SearchSettingsTable
RagSearch --> Embeddings
SearchSettings --> SearchService
SearchSettings --> MobileHook
```

- Mobile UI gets retrieval settings from the same shared `core` service contract as web.
- Mobile search still owns its own React Native interaction layer, but no longer owns retrieval presets as product logic.
- Backend remains unchanged in principle; the mobile task is mostly wiring and UX parity.

## Data Models
**What data do we need to manage?**

### Persisted retrieval settings
Use the shared `core/rag/searchSettings` model:

```typescript
interface RagSearchEditableSettings {
top_k: number
similarity_threshold: number
}

interface RagSearchReadonlySettings {
output_dimensionality: number
task_type_document: "RETRIEVAL_DOCUMENT"
task_type_query: "RETRIEVAL_QUERY"
load_more_overfetch: 1
max_top_k: 100
offset_delta_threshold: number
}
```

### Mobile local state
```typescript
interface MobileSearchModeState {
isAIEnabled: boolean
viewMode: "note" | "chunk"
}

interface MobilePrecisionState {
draftThreshold: number
committedThreshold: number
}
```

- `preset` is removed from mobile local state.
- Retrieval settings are sourced from the server-backed shared model instead.

## API Design
**How do components communicate?**

### Existing backend contracts to reuse
- `api-keys-status`
- already returns `gemini` and `ragSearch`
- `api-keys-upsert`
- already persists retrieval settings
- `rag-search`
- already accepts numeric `topK` and `threshold`
- already returns `chunks` plus `hasMore`

### Mobile service usage
- `ApiKeysSettingsService`
- remains responsible for Gemini key status/save/remove
- `RagSearchSettingsService`
- new mobile consumer for retrieval settings loading/updating

### Mobile search request model
```typescript
{
query: string
topK: ragSearchSettings.top_k
threshold: committedThreshold
filterTag?: string | null
}
```

## Component Breakdown
**What are the major building blocks?**

### Mobile settings
- Extend [`ui/mobile/components/settings/ApiKeysSettingsPanel.tsx`](/C:/Projects/EverFreeNote/ui/mobile/components/settings/ApiKeysSettingsPanel.tsx)
- keep Gemini key management
- add retrieval settings section(s)
- show editable `topK`
- show read-only retrieval metadata

### Mobile search controls
- Update [`ui/mobile/components/search/SearchControls.tsx`](/C:/Projects/EverFreeNote/ui/mobile/components/search/SearchControls.tsx)
- remove `AiSearchPresetSelector`
- add a mobile-friendly precision slider
- Update [`ui/mobile/hooks/useMobileSearchMode.ts`](/C:/Projects/EverFreeNote/ui/mobile/hooks/useMobileSearchMode.ts)
- remove persisted preset
- keep AI enabled flag and `Notes/Chunks` view mode

### Mobile AI search hook
- Update [`ui/mobile/hooks/useMobileAIPaginatedSearch.ts`](/C:/Projects/EverFreeNote/ui/mobile/hooks/useMobileAIPaginatedSearch.ts)
- consume persisted retrieval settings instead of `SEARCH_PRESETS`
- use backend `hasMore`
- align pagination behavior with web where appropriate

### Mobile results list
- Update [`ui/mobile/components/search/SearchResultsList.tsx`](/C:/Projects/EverFreeNote/ui/mobile/components/search/SearchResultsList.tsx)
- if needed, adapt chunk rendering and counts to the newer retrieval behavior
- preserve mobile-native list performance and gestures

## Design Decisions
**Why did we choose this approach?**

### 1. Reuse shared retrieval settings contract
- Reason: web already validated the model and backend contract.
- Benefit: consistent behavior across platforms and less drift.

### 2. Keep mobile-specific UI while matching web product semantics
- Reason: React Native interaction patterns differ, but product meaning should stay the same.
- Benefit: mobile feels native without inventing a second retrieval model.

### 3. Remove preset-based product logic from mobile
- Reason: presets are now legacy product UX superseded by persisted settings + precision slider.
- Benefit: web/mobile parity and simpler reasoning about search quality.

### 4. Extend existing API key panel instead of adding a new tab
- Reason: mobile settings currently consolidate external integrations in one place, and this feature is a continuation of Gemini/RAG configuration.
- Benefit: smaller UX surface and lower navigation churn.

## Non-Functional Requirements
**How should the system perform?**

- Performance:
- slider interactions must remain smooth
- search refetch only on slider commit/release
- list rendering should stay FlashList-friendly
- Reliability:
- fallback defaults must appear when retrieval settings fail to load
- Gemini key flow must not regress
- Maintainability:
- retrieval settings logic stays in shared core
- mobile-specific presentation stays in mobile components/hooks
- Consistency:
- mobile and web should apply the same persisted retrieval settings for the same user
79 changes: 79 additions & 0 deletions docs/ai/implementation/feature-mobile-rag-retrieval-tuning-ui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
phase: implementation
title: Mobile RAG Retrieval Tuning UI
description: Implementation notes for mobile retrieval settings and AI search precision tuning
---

# Implementation Guide

## Development Setup
**How do we get started?**

- Active branch: `feature-mobile-rag-retrieval-tuning-ui`
- Base docs lint passed before starting
- Dependency bootstrap:
- root `npm ci` attempted but failed on Windows due a locked native module in `node_modules`
- `ui/mobile` `npm ci` completed successfully
- mobile implementation added `@react-native-community/slider`
- mobile/shared Jest runtime also required `@babel/runtime` to load `core/*` imports during tests
- Continue using existing repository scripts for validation after implementation

## Code Structure
**How is the code organized?**

- Shared retrieval settings:
- `core/rag/searchSettings.ts`
- `core/services/ragSearchSettings.ts`
- Mobile search:
- `ui/mobile/app/(tabs)/search.tsx`
- `ui/mobile/hooks/useMobileSearchMode.ts`
- `ui/mobile/hooks/useMobileAIPaginatedSearch.ts`
- `ui/mobile/components/search/*`
- Mobile settings:
- `ui/mobile/components/settings/ApiKeysSettingsPanel.tsx`
- `ui/mobile/app/(tabs)/settings.tsx`

## Implementation Notes
**Key technical details to remember:**

### Core features
- Replace mobile preset-driven retrieval logic with shared persisted settings.
- Keep `isAIEnabled` and `viewMode` in mobile local state, but remove preset persistence.
- Persist `similarity_threshold` via `RagSearchSettingsService` on slider commit.
- Load `topK` and read-only retrieval metadata into the mobile settings panel.
- Keep Gemini key save/remove on the same settings screen and invalidate `apiKeysStatus` queries after successful saves.
- Expose raw AI chunks in mobile chunk view instead of flattening only two grouped note chunks.

### Patterns & Best Practices
- Follow the web feature’s product semantics, but keep mobile-native layout and controls.
- Prefer shared core constants/defaults over mobile-local retrieval constants where equivalent.
- Keep fallback/default rendering when settings fail to load.

## Integration Points
**How do pieces connect?**

- Mobile settings/search load retrieval settings via `api-keys-status`
- Mobile settings persist retrieval settings via `api-keys-upsert`
- Mobile AI search invokes `rag-search` with numeric `topK` and `threshold`
- Mobile search note mode internally overfetches chunk windows until it can fill the requested note page or prove there are no more note groups

## Error Handling
**How do we handle failures?**

- Show friendly settings error messages while still rendering defaults.
- Keep Gemini key failures isolated from retrieval settings rendering where possible.
- Avoid firing AI search while settings are still unresolved if the final values matter to the request.
- Keep precision save rollback behavior request-aware so a stale slider response does not overwrite a newer value.

## Performance Considerations
**How do we keep it fast?**

- Keep slider updates local and refetch only on commit.
- Preserve FlashList usage in mobile search results.
- Avoid unnecessary re-renders when toggling AI mode and view mode.

## Security Notes
**What security measures are in place?**

- Retrieval settings remain per-user and server-backed.
- Gemini API key handling stays in the existing encrypted backend flow.
70 changes: 70 additions & 0 deletions docs/ai/planning/feature-mobile-rag-retrieval-tuning-ui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
phase: planning
title: Mobile RAG Retrieval Tuning UI
description: Task breakdown for bringing retrieval tuning parity to the mobile app
---

# Project Planning & Task Breakdown

## Milestones
**What are the major checkpoints?**

- [x] Milestone 1: Mobile requirements/design docs created and validated
- [x] Milestone 2: Mobile settings and search UI wired to persisted retrieval settings
- [x] Milestone 3: Tests and validation pass for mobile retrieval tuning flow

## Task Breakdown
**What specific work needs to be done?**

### Phase 1: Mobile settings parity
- [x] Task 1.1: Extend mobile API key settings panel to load and show retrieval settings
- [x] Task 1.2: Add editable `topK` controls and read-only retrieval metadata to mobile settings
- [x] Task 1.3: Preserve Gemini key save/remove flows and fallback/default states

### Phase 2: Mobile search parity
- [x] Task 2.1: Remove preset selector from mobile search controls
- [x] Task 2.2: Add precision slider with commit-on-release behavior
- [x] Task 2.3: Update mobile search mode state to remove preset persistence
- [x] Task 2.4: Update mobile AI search hook to use persisted retrieval settings instead of presets
- [x] Task 2.5: Align mobile `Load more` handling with the current backend contract

### Phase 3: Testing & regression coverage
- [x] Task 3.1: Update mobile unit tests for settings panels
- [x] Task 3.2: Add mobile tests for search controls / search hook behavior
- [x] Task 3.3: Run mobile-targeted tests and full validation

## Dependencies
**What needs to happen in what order?**

- Retrieval settings UI depends on the existing shared `RagSearchSettingsService`, which is already available.
- Search screen updates depend on replacing preset-based state in `useMobileSearchMode`.
- Search hook updates depend on the same shared retrieval settings model used in settings.
- Tests should be updated after the settings/search contracts settle.

## Timeline & Estimates
**When will things be done?**

- Docs + implementation alignment: small
- Mobile settings/search implementation: medium
- Testing and regression pass: medium

Overall estimate: moderate continuation feature, smaller than the original web feature because backend/core contracts already exist.

## Risks & Mitigation
**What could go wrong?**

- Risk: mobile search still has platform-specific assumptions tied to presets
- Mitigation: isolate preset removal to `useMobileSearchMode` and `useMobileAIPaginatedSearch`
- Risk: mobile settings panel becomes too crowded
- Mitigation: use sectioned layout and keep read-only metadata compact
- Risk: mobile tests may be more brittle around sliders and async settings loads
- Mitigation: prefer hook/service-level assertions plus focused component tests
- Risk: mobile Jest may fail before reaching feature tests because shared core imports resolve through the repository root
- Mitigation: keep `@babel/runtime` available for the shared `core/*` import graph and patch virtual-only mocks in `tests/setupTests.ts`

## Resources Needed
**What do we need to succeed?**

- Existing shared retrieval settings service/model in `core`
- Existing mobile search/settings test harness
- Existing backend contracts already deployed for web parity
Loading
Loading