feat: add AI knowledge analysis MVP
This commit is contained in:
@@ -0,0 +1 @@
|
||||
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
|
||||
395
.trellis/tasks/07-04-ai-agent-knowledge-analysis/design.md
Normal file
395
.trellis/tasks/07-04-ai-agent-knowledge-analysis/design.md
Normal file
@@ -0,0 +1,395 @@
|
||||
# AI Agent Knowledge Analysis Design
|
||||
|
||||
## Overview
|
||||
|
||||
Implement the MVP as a server-side LangChain AI module with PostgreSQL/pgvector-backed knowledge retrieval and a structured elder AI analysis panel in the existing elder list workflow.
|
||||
|
||||
The MVP is not a chat assistant. It is a deterministic product workflow:
|
||||
|
||||
1. Authorized user opens an elder's AI analysis dialog from the elder list.
|
||||
2. Server loads only the resident data families the user can read.
|
||||
3. Server retrieves enabled platform shared knowledge and enabled active-organization knowledge.
|
||||
4. LangChain generates a fixed structured analysis.
|
||||
5. Server saves completed or failed history, writes audit logs, and returns structured JSON.
|
||||
6. UI renders latest analysis, history, citations, recommendations, and restricted placeholders where permissions do not allow detail access.
|
||||
|
||||
## Module Boundaries
|
||||
|
||||
### New Module
|
||||
|
||||
Create `modules/ai/`:
|
||||
|
||||
- `modules/ai/types.ts`
|
||||
- Zod-compatible validation helpers or TypeScript runtime validators for knowledge entries, analysis output, history status, risk levels, citation shapes, and data scopes.
|
||||
- `modules/ai/server/config.ts`
|
||||
- Reads `AI_BASE_URL`, `AI_API_KEY`, `AI_CHAT_MODEL`, `AI_EMBEDDING_MODEL`, and optional timeout/limit settings.
|
||||
- `modules/ai/server/knowledge.ts`
|
||||
- CRUD for knowledge entries.
|
||||
- Chunking and embedding on save.
|
||||
- Scope-filtered retrieval from pgvector.
|
||||
- `modules/ai/server/elder-context.ts`
|
||||
- Builds full resident graph with permission-aware optional data families.
|
||||
- `modules/ai/server/analysis.ts`
|
||||
- Runs LangChain analysis flow.
|
||||
- Validates structured output.
|
||||
- Saves completed/failed history.
|
||||
- `modules/ai/components/KnowledgeManagementClient.tsx`
|
||||
- Settings UI for manual knowledge entries.
|
||||
- `modules/ai/components/ElderAiAnalysisDialog.tsx`
|
||||
- Elder row dialog panel for generation, latest analysis, history, and citations.
|
||||
|
||||
### Existing Integration Points
|
||||
|
||||
- `modules/core/server/schema.ts`
|
||||
- Add AI enums/tables.
|
||||
- `modules/core/types.ts`
|
||||
- Add permissions and exported AI-related shared types as needed.
|
||||
- `modules/core/server/permissions.ts`
|
||||
- Seed AI/knowledge permission definitions and default role grants.
|
||||
- `app/api/ai/...`
|
||||
- New API routes for knowledge and elder analysis.
|
||||
- `app/(app)/app/settings/knowledge/page.tsx`
|
||||
- New settings route.
|
||||
- `app/(app)/app/[organizationSlug]/settings/knowledge/page.tsx`
|
||||
- Scoped route re-export.
|
||||
- `modules/shared/lib/navigation.ts`
|
||||
- Add settings navigation item visible with `knowledge:read`.
|
||||
- `modules/elders/components/EldersClient.tsx`
|
||||
- Add per-row AI analysis action and dialog.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Add runtime dependencies:
|
||||
|
||||
- `@langchain/openai`
|
||||
- `@langchain/core`
|
||||
- `langchain`
|
||||
|
||||
Add pgvector support through Drizzle/Postgres:
|
||||
|
||||
- Use PostgreSQL `vector` extension.
|
||||
- Prefer a pgvector-capable Postgres image for local development instead of plain `postgres:17-alpine`.
|
||||
- If Drizzle vector column support is insufficient for the exact version, use custom SQL migration for vector extension/index while keeping typed table metadata in schema.
|
||||
|
||||
Vercel AI SDK remains out of the MVP runtime path.
|
||||
|
||||
## Data Model
|
||||
|
||||
### Permissions
|
||||
|
||||
Add permission IDs:
|
||||
|
||||
- `ai:read`
|
||||
- `ai:manage`
|
||||
- `knowledge:read`
|
||||
- `knowledge:manage`
|
||||
|
||||
Default grants:
|
||||
|
||||
- `platform_admin`: all four.
|
||||
- `org_admin`: all four.
|
||||
- `manager`: all four.
|
||||
- `caregiver`: `ai:read`, `knowledge:read`.
|
||||
- `viewer`, `family`, `resident`: none.
|
||||
|
||||
### Knowledge Entries
|
||||
|
||||
Table: `ai_knowledge_entries`
|
||||
|
||||
Fields:
|
||||
|
||||
- `id uuid primary key`
|
||||
- `scope enum('platform', 'organization')`
|
||||
- `organizationId uuid null references organizations(id) on delete cascade`
|
||||
- `title text not null`
|
||||
- `category text not null default ''`
|
||||
- `tags text not null default ''`
|
||||
- `body text not null`
|
||||
- `status enum('enabled', 'disabled') not null default 'enabled'`
|
||||
- `createdByAccountId uuid null references accounts(id)`
|
||||
- `updatedByAccountId uuid null references accounts(id)`
|
||||
- `createdAt timestamptz not null default now()`
|
||||
- `updatedAt timestamptz not null default now()`
|
||||
|
||||
Rules:
|
||||
|
||||
- `scope='platform'` requires `organizationId IS NULL`.
|
||||
- `scope='organization'` requires `organizationId` to match the active organization.
|
||||
- Platform entries require platform-level authorization to manage.
|
||||
- Organization entries require active organization plus `knowledge:manage`.
|
||||
|
||||
### Knowledge Chunks
|
||||
|
||||
Table: `ai_knowledge_chunks`
|
||||
|
||||
Fields:
|
||||
|
||||
- `id uuid primary key`
|
||||
- `entryId uuid not null references ai_knowledge_entries(id) on delete cascade`
|
||||
- `organizationId uuid null`
|
||||
- `scope enum('platform', 'organization')`
|
||||
- `chunkIndex integer not null`
|
||||
- `content text not null`
|
||||
- `embedding vector(<embedding_dimensions>) not null`
|
||||
- `sourceTitle text not null`
|
||||
- `sourceCategory text not null default ''`
|
||||
- `createdAt timestamptz not null default now()`
|
||||
|
||||
Indexes:
|
||||
|
||||
- B-tree on `(scope, organization_id)`.
|
||||
- Vector index for embedding similarity, using pgvector operator/index supported by deployment.
|
||||
|
||||
Embedding dimensions are tied to `AI_EMBEDDING_MODEL`; document the chosen default in env configuration.
|
||||
|
||||
### Elder AI Analyses
|
||||
|
||||
Table: `elder_ai_analyses`
|
||||
|
||||
Fields:
|
||||
|
||||
- `id uuid primary key`
|
||||
- `organizationId uuid not null references organizations(id) on delete cascade`
|
||||
- `elderId uuid not null references elders(id) on delete cascade`
|
||||
- `actorAccountId uuid null references accounts(id)`
|
||||
- `status enum('completed', 'failed') not null`
|
||||
- `dataScopes text not null`
|
||||
- `resultJson jsonb null`
|
||||
- `citationsJson jsonb not null default '[]'::jsonb`
|
||||
- `modelSummaryJson jsonb not null default '{}'::jsonb`
|
||||
- `errorCategory text not null default ''`
|
||||
- `errorReason text not null default ''`
|
||||
- `createdAt timestamptz not null default now()`
|
||||
|
||||
Rules:
|
||||
|
||||
- Completed rows require a valid `resultJson`.
|
||||
- Failed rows must not store prompt, full resident context, or raw provider errors.
|
||||
- `dataScopes` stores a stable comma-separated list or JSON array; use JSONB if Drizzle ergonomics are acceptable.
|
||||
|
||||
## Authorization Model
|
||||
|
||||
### Generate Analysis
|
||||
|
||||
Required:
|
||||
|
||||
- Authenticated session.
|
||||
- Active organization.
|
||||
- `ai:read`.
|
||||
- `elder:read`.
|
||||
- Target elder belongs to active organization.
|
||||
|
||||
Optional data families:
|
||||
|
||||
- `health` only if `health:read`.
|
||||
- `care` only if `care:read`.
|
||||
- `family` only if `family:read`.
|
||||
- `admission` only if `admission:read`.
|
||||
- `facility` only if `facility:read`.
|
||||
- `alert` only if `alert:read`.
|
||||
- `incident` only if `incident:read`.
|
||||
- `knowledge` only if `knowledge:read`.
|
||||
|
||||
`dataScopes` records exactly which families were included.
|
||||
|
||||
### View Analysis History
|
||||
|
||||
History list can show safe metadata for rows in the active organization and elder when the user has `ai:read` and `elder:read`.
|
||||
|
||||
History detail requires all permissions implied by `dataScopes`. If missing any scope, return or render a restricted placeholder and do not include `resultJson`/citations content.
|
||||
|
||||
### Knowledge Retrieval
|
||||
|
||||
Retrieval requires `knowledge:read`.
|
||||
|
||||
Eligible entries:
|
||||
|
||||
- `scope='platform'`, `status='enabled'`.
|
||||
- `scope='organization'`, `organizationId = activeOrganizationId`, `status='enabled'`.
|
||||
|
||||
No organization-private chunks from other organizations may be retrievable.
|
||||
|
||||
## LangChain Flow
|
||||
|
||||
### Provider
|
||||
|
||||
Use OpenAI-compatible configuration:
|
||||
|
||||
- `AI_BASE_URL`
|
||||
- `AI_API_KEY`
|
||||
- `AI_CHAT_MODEL`
|
||||
- `AI_EMBEDDING_MODEL`
|
||||
|
||||
`config.ts` validates required settings before generation/embedding and returns structured failures for missing configuration.
|
||||
|
||||
### Retrieval
|
||||
|
||||
1. Convert resident query/context summary into embedding.
|
||||
2. Query `ai_knowledge_chunks` with pgvector similarity.
|
||||
3. Filter by allowed scopes before vector ranking.
|
||||
4. Return top K chunks with source metadata:
|
||||
- source type: `knowledge`
|
||||
- entry id
|
||||
- chunk id
|
||||
- title
|
||||
- category
|
||||
- scope
|
||||
|
||||
### Resident Context Assembly
|
||||
|
||||
Build one typed object:
|
||||
|
||||
- Elder basics.
|
||||
- Current bed/admission context.
|
||||
- Admission history.
|
||||
- Health profile.
|
||||
- Recent vitals.
|
||||
- Chronic conditions.
|
||||
- Health anomaly reviews.
|
||||
- Care tasks.
|
||||
- Alert triggers/rules where relevant.
|
||||
- System incidents matched by elder/bed where relevant.
|
||||
- Family contacts/visits/feedback.
|
||||
- Retrieved knowledge snippets.
|
||||
|
||||
Use batch queries and `Promise.all` where independent. No `await` in loops.
|
||||
|
||||
### Structured Output
|
||||
|
||||
Output schema:
|
||||
|
||||
- `overallRiskLevel`: `low | medium | high | critical | unknown`
|
||||
- `summary`: string
|
||||
- `keyFindings`: array of:
|
||||
- `category`: string
|
||||
- `severity`: `info | warning | critical`
|
||||
- `evidence`: string
|
||||
- `citationIds`: string[]
|
||||
- `recommendations`: array of:
|
||||
- `priority`: `low | normal | high | urgent`
|
||||
- `action`: string
|
||||
- `reason`: string
|
||||
- `citationIds`: string[]
|
||||
- `dataGaps`: string[]
|
||||
- `citations`: array of:
|
||||
- `id`: string
|
||||
- `sourceType`: `record | knowledge`
|
||||
- `sourceId`: string
|
||||
- `title`: string
|
||||
- `excerpt`: string
|
||||
- `confidence`: number from 0 to 1
|
||||
- `modelSummary`: object with provider base URL host, chat model, embedding model, and generation timestamp, excluding API key.
|
||||
|
||||
Use LangChain structured output where possible. Validate again server-side before saving.
|
||||
|
||||
## API Design
|
||||
|
||||
### Elder Analysis
|
||||
|
||||
- `GET /api/ai/elders/[id]/analyses`
|
||||
- Returns latest allowed analysis metadata/detail and history list.
|
||||
- Redacts detail for records whose `dataScopes` exceed current permissions.
|
||||
- `POST /api/ai/elders/[id]/analyses`
|
||||
- Synchronously generates a new analysis.
|
||||
- Returns `{ success: true, reason, analysis }` on completion.
|
||||
- On failure, saves failed history and audit log, then returns `{ success: false, reason }`.
|
||||
|
||||
### Knowledge
|
||||
|
||||
- `GET /api/ai/knowledge`
|
||||
- Requires `knowledge:read`.
|
||||
- Lists platform and active organization entries visible to caller.
|
||||
- `POST /api/ai/knowledge`
|
||||
- Requires `knowledge:manage`.
|
||||
- Creates entry, chunks, embeds, writes audit log.
|
||||
- `PATCH /api/ai/knowledge/[id]`
|
||||
- Requires `knowledge:manage`.
|
||||
- Updates entry and rebuilds chunks/embeddings.
|
||||
- `DELETE /api/ai/knowledge/[id]`
|
||||
- Requires `knowledge:manage`.
|
||||
- Deletes entry and cascading chunks.
|
||||
|
||||
All routes return the existing API response shape with `Cache-Control: no-store`.
|
||||
|
||||
## UI Design
|
||||
|
||||
### Elder List
|
||||
|
||||
In `EldersClient`:
|
||||
|
||||
- Add AI analysis button per row for users with `ai:read`.
|
||||
- Use lucide icon such as `Sparkles`.
|
||||
- Open `Dialog` with `width="wide"`.
|
||||
- Dialog sections:
|
||||
- Resident summary.
|
||||
- Generate button with loading state.
|
||||
- Latest analysis summary.
|
||||
- Findings and recommendations.
|
||||
- Data gaps.
|
||||
- Citations.
|
||||
- History list with restricted placeholders.
|
||||
|
||||
No chat input and no one-click business creation.
|
||||
|
||||
### Knowledge Settings Page
|
||||
|
||||
Route: `/settings/knowledge`
|
||||
|
||||
Features:
|
||||
|
||||
- List entries by scope/status/category/search.
|
||||
- Create/edit dialog with title, body, category, tags, scope, enabled/disabled.
|
||||
- Disable mutations when missing `knowledge:manage`.
|
||||
- Show embedding/rebuild status through response messages; no background jobs.
|
||||
|
||||
## Audit And Logging
|
||||
|
||||
Audit actions:
|
||||
|
||||
- `ai.elderAnalysis.generate`
|
||||
- `ai.elderAnalysis.generateFailed`
|
||||
- `ai.knowledge.create`
|
||||
- `ai.knowledge.update`
|
||||
- `ai.knowledge.delete`
|
||||
- `ai.knowledge.disable`
|
||||
- `ai.knowledge.enable`
|
||||
|
||||
Audit records include actor, organization, target type/id, result, and sanitized reason.
|
||||
|
||||
Do not store:
|
||||
|
||||
- Full prompts.
|
||||
- Full resident context snapshots.
|
||||
- Raw provider errors.
|
||||
- API keys.
|
||||
|
||||
## Failure Handling
|
||||
|
||||
Generation failures are classified:
|
||||
|
||||
- `missing_configuration`
|
||||
- `provider_error`
|
||||
- `timeout`
|
||||
- `schema_validation_failed`
|
||||
- `retrieval_failed`
|
||||
- `unknown`
|
||||
|
||||
On failure:
|
||||
|
||||
1. Save failed analysis history with sanitized category/reason.
|
||||
2. Write audit log.
|
||||
3. Return structured API failure.
|
||||
4. UI shows a concise error state and keeps prior completed history visible.
|
||||
|
||||
## Rollout And Compatibility
|
||||
|
||||
- Requires database migration for pgvector extension, AI enums, knowledge tables, chunk table, analysis table, and permissions.
|
||||
- Local `compose.yaml` should use a pgvector-capable PostgreSQL image or document manual extension installation.
|
||||
- Production deployment must verify `CREATE EXTENSION vector` support before migration.
|
||||
- If AI env vars are missing, knowledge CRUD can still work except embedding-dependent save should fail gracefully; analysis generation should return a structured configuration failure.
|
||||
|
||||
## Open Trade-Offs
|
||||
|
||||
- Embedding dimensions depend on the selected embedding model. The implementation should define a default and document migration impact if changed.
|
||||
- Synchronous generation is acceptable for MVP but can be replaced later by async jobs using the same history table status field.
|
||||
- Platform shared knowledge increases utility but requires careful scope filters in every retrieval query.
|
||||
@@ -0,0 +1 @@
|
||||
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
|
||||
305
.trellis/tasks/07-04-ai-agent-knowledge-analysis/implement.md
Normal file
305
.trellis/tasks/07-04-ai-agent-knowledge-analysis/implement.md
Normal file
@@ -0,0 +1,305 @@
|
||||
# AI Agent Knowledge Analysis Implementation Plan
|
||||
|
||||
## Preconditions
|
||||
|
||||
- User reviews and approves `prd.md`, `design.md`, and `implement.md`.
|
||||
- Task status is moved from `planning` to `in_progress` with `task.py start`.
|
||||
- Before editing code in Phase 2, load `trellis-before-dev` and relevant specs:
|
||||
- `.trellis/spec/shared/code-quality.md`
|
||||
- `.trellis/spec/shared/typescript.md`
|
||||
- `.trellis/spec/shared/dependencies.md`
|
||||
- `.trellis/spec/backend/directory-structure.md`
|
||||
- `.trellis/spec/backend/database.md`
|
||||
- `.trellis/spec/backend/authentication.md`
|
||||
- `.trellis/spec/backend/type-safety.md`
|
||||
- `.trellis/spec/backend/quality.md`
|
||||
- `.trellis/spec/frontend/components.md`
|
||||
- `.trellis/spec/frontend/type-safety.md`
|
||||
- `.trellis/spec/frontend/quality.md`
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
### 1. Dependencies And Environment
|
||||
|
||||
- Add LangChain runtime packages:
|
||||
- `langchain`
|
||||
- `@langchain/core`
|
||||
- `@langchain/openai`
|
||||
- Decide and document default embedding dimension for `AI_EMBEDDING_MODEL`.
|
||||
- Add env handling in `modules/ai/server/config.ts`:
|
||||
- `AI_BASE_URL`
|
||||
- `AI_API_KEY`
|
||||
- `AI_CHAT_MODEL`
|
||||
- `AI_EMBEDDING_MODEL`
|
||||
- Update local PostgreSQL image or setup notes so pgvector is available.
|
||||
|
||||
Validation:
|
||||
|
||||
- `pnpm install`
|
||||
- `pnpm type-check`
|
||||
|
||||
Rollback:
|
||||
|
||||
- Remove added dependencies and AI env usage if the AI module is backed out.
|
||||
|
||||
### 2. Database Schema And Migration
|
||||
|
||||
- Update `modules/core/server/schema.ts`:
|
||||
- AI enums for knowledge scope/status and analysis status.
|
||||
- `aiKnowledgeEntries`.
|
||||
- `aiKnowledgeChunks`.
|
||||
- `elderAiAnalyses`.
|
||||
- Add pgvector extension migration support.
|
||||
- Generate Drizzle migration with `pnpm db:generate`.
|
||||
- Manually inspect generated SQL for:
|
||||
- `CREATE EXTENSION IF NOT EXISTS vector`.
|
||||
- Correct foreign keys.
|
||||
- Correct indexes.
|
||||
- Correct vector column type/dimension.
|
||||
|
||||
Validation:
|
||||
|
||||
- `pnpm db:generate`
|
||||
- `pnpm type-check`
|
||||
- Apply migration locally when DB is available: `pnpm db:migrate`.
|
||||
|
||||
Rollback:
|
||||
|
||||
- Drop AI tables and extension-dependent indexes in a rollback migration if needed.
|
||||
- Do not drop `vector` extension automatically if other future objects may use it.
|
||||
|
||||
### 3. Permissions And Role Seeding
|
||||
|
||||
- Update `modules/core/types.ts`:
|
||||
- Add `ai:read`, `ai:manage`, `knowledge:read`, `knowledge:manage`.
|
||||
- Update `modules/core/server/permissions.ts`:
|
||||
- Add permission definitions.
|
||||
- Update default role grants:
|
||||
- `platform_admin`: all four.
|
||||
- `org_admin`: all four.
|
||||
- `manager`: all four.
|
||||
- `caregiver`: `ai:read`, `knowledge:read`.
|
||||
- `viewer`, `family`, `resident`: none.
|
||||
- Ensure `ensureSystemDefaults()` upserts permissions and role grants without deleting custom grants.
|
||||
|
||||
Validation:
|
||||
|
||||
- `pnpm type-check`
|
||||
- Targeted tests or assertions for seeded permission definitions and role grants.
|
||||
|
||||
Rollback:
|
||||
|
||||
- Remove permissions from default grants only through an intentional migration/seed change; avoid deleting custom user role state.
|
||||
|
||||
### 4. AI Domain Types
|
||||
|
||||
- Create `modules/ai/types.ts`.
|
||||
- Define:
|
||||
- Knowledge entry input and status/scope values.
|
||||
- Analysis status values.
|
||||
- Data scope values.
|
||||
- Risk/severity/priority values.
|
||||
- Structured analysis output type and runtime validator.
|
||||
- Citation type.
|
||||
- Sanitized error category type.
|
||||
- Avoid `any`; use explicit `unknown` validation helpers when parsing API bodies or AI output.
|
||||
|
||||
Validation:
|
||||
|
||||
- Unit tests for validators if they contain non-trivial parsing.
|
||||
- `pnpm type-check`
|
||||
|
||||
Rollback:
|
||||
|
||||
- Types are isolated; remove module if feature is backed out.
|
||||
|
||||
### 5. Knowledge Service
|
||||
|
||||
- Create `modules/ai/server/knowledge.ts`.
|
||||
- Implement:
|
||||
- List visible entries by permission and active organization.
|
||||
- Create/update/delete entries with scope validation.
|
||||
- Server-side chunking.
|
||||
- Embedding generation through LangChain OpenAI-compatible embeddings.
|
||||
- Chunk rebuild on create/update.
|
||||
- Scope-filtered retrieval for platform shared + active organization entries.
|
||||
- Write audit logs for create/update/delete/enable/disable.
|
||||
- Ensure no organization-private chunks from other organizations can be retrieved.
|
||||
|
||||
Validation:
|
||||
|
||||
- Tests for scope filtering:
|
||||
- Platform shared visible to organization user.
|
||||
- Own organization visible.
|
||||
- Other organization not visible.
|
||||
- Disabled entries not retrieved.
|
||||
- Tests for mutation permission failures.
|
||||
|
||||
Rollback:
|
||||
|
||||
- Disable `/settings/knowledge` navigation and API routes if embedding is unavailable.
|
||||
- Existing tables can remain unused.
|
||||
|
||||
### 6. Elder Context Service
|
||||
|
||||
- Create `modules/ai/server/elder-context.ts`.
|
||||
- Implement permission-aware resident graph assembly:
|
||||
- Always include elder basics after `elder:read`.
|
||||
- Include health only with `health:read`.
|
||||
- Include care only with `care:read`.
|
||||
- Include family only with `family:read`.
|
||||
- Include admission/facility only with matching read permissions.
|
||||
- Include alert/incident only with matching read permissions.
|
||||
- Include knowledge only with `knowledge:read`.
|
||||
- Return `dataScopes` exactly matching included families.
|
||||
- Use batch queries and `Promise.all` for independent loads.
|
||||
|
||||
Validation:
|
||||
|
||||
- Tests for data family inclusion/exclusion by permissions.
|
||||
- Tests that target elder must belong to active organization.
|
||||
|
||||
Rollback:
|
||||
|
||||
- This service is isolated under `modules/ai`; remove API use if feature is disabled.
|
||||
|
||||
### 7. Analysis Service
|
||||
|
||||
- Create `modules/ai/server/analysis.ts`.
|
||||
- Implement:
|
||||
- Generate structured analysis synchronously with LangChain.
|
||||
- Validate AI output against fixed schema.
|
||||
- Save `completed` history with result/citations/model summary/data scopes.
|
||||
- On failure, save `failed` history with sanitized error category/reason.
|
||||
- Write success/failure audit logs.
|
||||
- Redact history details when current permissions do not satisfy stored `dataScopes`.
|
||||
- Do not store full prompts, full context snapshots, API keys, or raw provider errors.
|
||||
|
||||
Validation:
|
||||
|
||||
- Tests for:
|
||||
- Missing config -> structured failure + failed history.
|
||||
- Schema validation failure -> failed history.
|
||||
- History detail redaction when permissions are insufficient.
|
||||
- Completed history shape.
|
||||
|
||||
Rollback:
|
||||
|
||||
- Keep history rows as audit evidence; hide UI/API if provider issues block rollout.
|
||||
|
||||
### 8. API Routes
|
||||
|
||||
- Add elder analysis routes:
|
||||
- `app/api/ai/elders/[id]/analyses/route.ts`
|
||||
- `GET`: latest/history with permission-aware redaction.
|
||||
- `POST`: synchronous generation.
|
||||
- Add knowledge routes:
|
||||
- `app/api/ai/knowledge/route.ts`
|
||||
- `GET`, `POST`.
|
||||
- `app/api/ai/knowledge/[id]/route.ts`
|
||||
- `PATCH`, `DELETE`.
|
||||
- Use existing `requirePermission`, `jsonSuccess`, `jsonFailure`, `readJsonBody`, and `recordAuditLog` patterns.
|
||||
- Preserve `Cache-Control: no-store` through existing helpers.
|
||||
|
||||
Validation:
|
||||
|
||||
- Route tests for auth/permission failures and structured responses.
|
||||
- `pnpm type-check`
|
||||
|
||||
Rollback:
|
||||
|
||||
- Remove routes or return feature-disabled failures while keeping data.
|
||||
|
||||
### 9. Knowledge Settings UI
|
||||
|
||||
- Create:
|
||||
- `app/(app)/app/settings/knowledge/page.tsx`
|
||||
- `app/(app)/app/[organizationSlug]/settings/knowledge/page.tsx`
|
||||
- `modules/ai/components/KnowledgeManagementClient.tsx`
|
||||
- Update:
|
||||
- `modules/shared/lib/navigation.ts`
|
||||
- `modules/shared/components/AppSidebarNav.tsx` icon map if a new icon key is needed.
|
||||
- UI supports:
|
||||
- List/filter/search.
|
||||
- Create/edit dialog.
|
||||
- Enable/disable/delete.
|
||||
- Read-only view if missing `knowledge:manage`.
|
||||
- Follow existing settings/client component patterns.
|
||||
|
||||
Validation:
|
||||
|
||||
- Manual browser check.
|
||||
- Type-check/lint.
|
||||
|
||||
Rollback:
|
||||
|
||||
- Remove nav entry and route.
|
||||
|
||||
### 10. Elder Analysis UI
|
||||
|
||||
- Update `modules/elders/components/EldersClient.tsx`.
|
||||
- Add `AI 分析` row action for authorized users.
|
||||
- Create `modules/ai/components/ElderAiAnalysisDialog.tsx`.
|
||||
- Dialog displays:
|
||||
- Elder summary.
|
||||
- Generate button/loading state.
|
||||
- Latest completed analysis.
|
||||
- Failed state if latest attempt failed.
|
||||
- Findings, recommendations, data gaps.
|
||||
- Citations.
|
||||
- History list with restricted placeholders.
|
||||
- No chat input.
|
||||
- No one-click business mutation.
|
||||
|
||||
Validation:
|
||||
|
||||
- Manual browser check for desktop/mobile widths.
|
||||
- Confirm button text fits and table layout remains stable.
|
||||
- Verify unauthorized users do not see the action.
|
||||
|
||||
Rollback:
|
||||
|
||||
- Remove row action; API/history remains dormant.
|
||||
|
||||
### 11. Quality Gate
|
||||
|
||||
Run:
|
||||
|
||||
- `pnpm lint`
|
||||
- `pnpm type-check`
|
||||
- `pnpm test` if route/domain tests were added.
|
||||
- `pnpm build` before final completion if time and environment allow.
|
||||
|
||||
Manual checks:
|
||||
|
||||
- Knowledge CRUD as authorized admin/manager.
|
||||
- Knowledge read-only as caregiver.
|
||||
- Elder analysis generation with configured AI provider.
|
||||
- Missing AI config failure.
|
||||
- History redaction across roles.
|
||||
- Other-organization knowledge cannot appear in retrieval.
|
||||
|
||||
## Risky Files
|
||||
|
||||
- `modules/core/server/schema.ts`
|
||||
- `modules/core/types.ts`
|
||||
- `modules/core/server/permissions.ts`
|
||||
- `compose.yaml`
|
||||
- `drizzle/*`
|
||||
- `modules/elders/components/EldersClient.tsx`
|
||||
- `modules/shared/lib/navigation.ts`
|
||||
|
||||
## Rollback Points
|
||||
|
||||
- After dependency install: revert package changes if LangChain package compatibility fails.
|
||||
- After schema migration generation: inspect SQL before applying.
|
||||
- After permissions update: verify default role grants before touching UI.
|
||||
- After API routes: keep UI disabled until permission and scope tests pass.
|
||||
- After UI: remove nav/row entry if backend generation is not production-ready.
|
||||
|
||||
## Follow-Up Checks Before Start
|
||||
|
||||
- Confirm pgvector deployment support on the target PostgreSQL server.
|
||||
- Pick and document embedding dimensions for the configured default embedding model.
|
||||
- Confirm production AI provider and env var names.
|
||||
- Decide whether to add seed knowledge entries for smoke testing.
|
||||
158
.trellis/tasks/07-04-ai-agent-knowledge-analysis/prd.md
Normal file
158
.trellis/tasks/07-04-ai-agent-knowledge-analysis/prd.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# AI agent knowledge analysis
|
||||
|
||||
## Goal
|
||||
|
||||
Add an AI capability layer for TeaTea Pension that can use agent-style orchestration, retrieve organization-scoped knowledge, and provide AI analysis in relevant care-operation workflows.
|
||||
|
||||
The MVP workflow is elder profile AI analysis: given one resident, the system should gather authorized, organization-scoped resident context, retrieve relevant knowledge, and produce a cited, structured operational analysis for staff review.
|
||||
|
||||
The MVP interaction is a fixed "generate AI analysis" panel, not a conversational assistant. The panel should produce structured output such as risk summary, key evidence, recommended actions, source citations, and confidence.
|
||||
|
||||
The MVP entry point should be an "AI 分析" action in each elder table row. Clicking it opens a `wide` dialog panel that shows elder context, a generate action, the latest analysis, analysis history, and citations.
|
||||
|
||||
The MVP resident context should use the full available resident graph: elder basics, current bed/admission context, admission history, health profile, recent vitals, chronic conditions, health anomaly reviews, care tasks, alerts/incidents, family feedback, and relevant knowledge-base snippets.
|
||||
|
||||
MVP knowledge-base content should be manually maintained as structured knowledge entries with title, body, category/tags, scope, organization scope when applicable, and enabled status. On save, the server should chunk and embed the content into pgvector-backed storage. File upload, OCR, web crawling, and external-system sync are out of scope for MVP ingestion.
|
||||
|
||||
MVP retrieval should support platform shared knowledge plus organization-private knowledge. Ordinary organization users can retrieve enabled platform shared entries and enabled entries for their active organization. Platform knowledge is maintained by platform-level authorized users; organization knowledge is maintained by organization-level authorized users.
|
||||
|
||||
MVP must include a `/settings/knowledge` management page under the existing settings area. The sidebar entry should live in the "管理系统" group, be visible to `knowledge:read`, and allow create/edit/enable/disable/delete only with `knowledge:manage`.
|
||||
|
||||
MVP elder analyses should be persisted as history records with organization, elder, actor, structured result, source citations, model configuration summary, status, and creation time. Persisting history supports auditability, comparison over time, and token-cost control.
|
||||
|
||||
MVP AI analysis output must be a fixed structured schema rendered by the frontend rather than free-form text. The schema should include `overallRiskLevel`, `summary`, `keyFindings[]`, `recommendations[]`, `dataGaps[]`, `citations[]`, `confidence`, and `modelSummary`. Findings should include category, severity, evidence, and citation references. Recommendations should remain advisory and must not create business drafts.
|
||||
|
||||
MVP analysis generation should run synchronously in the request. The UI should show a loading state while generation is in progress. Analysis history should support at least `completed` and `failed` statuses so failures are visible and auditable without requiring an async job system.
|
||||
|
||||
On generation failure, the system should save a `failed` analysis history record and write an audit log. Failed history records must store only sanitized error category and brief reason, such as `provider_error`, `timeout`, or `schema_validation_failed`; they must not store full prompts, resident context, sensitive data, or raw provider errors.
|
||||
|
||||
Each analysis history record must store `dataScopes` describing the data families used to generate it, such as `elder`, `health`, `care`, `family`, `admission`, `alert`, `incident`, and `knowledge`. Viewing a history detail requires `ai:read`, `elder:read`, active organization access, and all read permissions implied by that record's `dataScopes`; otherwise the UI should show a restricted placeholder rather than the analysis content.
|
||||
|
||||
The broader planning objective still covers:
|
||||
|
||||
- LangChain + agent module.
|
||||
- Knowledge-base retrieval.
|
||||
- AI analysis from multiple places in the product.
|
||||
|
||||
The feature should improve operational decision support without weakening tenant isolation, role permissions, auditability, or existing deterministic workflows.
|
||||
|
||||
## Confirmed Facts
|
||||
|
||||
- The application is a single-repo Next.js 15 / React 19 / TypeScript app with API routes, Drizzle ORM, PostgreSQL, and TailwindCSS. See `package.json`.
|
||||
- Runtime dependencies currently do not include `ai`, `@ai-sdk/*`, `langchain`, vector database clients, or embedding providers. See `package.json`.
|
||||
- Local infrastructure currently runs a single `postgres:17-alpine` service, and Drizzle migrations are generated from `modules/core/server/schema.ts`. There is no existing pgvector extension or external vector database configuration. See `compose.yaml` and `drizzle.config.ts`.
|
||||
- Project specs already contain Vercel AI SDK guidance for backend and frontend AI features in `.trellis/spec/backend/ai-sdk-integration.md` and `.trellis/spec/frontend/ai-sdk-integration.md`.
|
||||
- The actual backend code uses `modules/core/server/*` for database, auth, audit, permissions, and schema; it is not using the package layout shown in some generic specs.
|
||||
- Authentication uses a custom `teatea_session` cookie and Drizzle-backed `sessions`, `accounts`, `organizations`, `memberships`, `roles`, and permissions. See `modules/core/server/auth.ts` and `.trellis/spec/backend/authentication.md`.
|
||||
- Most operational tables are tenant-scoped by `organizationId`, and resident-specific data often includes `elderId`. See `modules/core/server/schema.ts`.
|
||||
- Current permission families include care, health, device, notice, alert, family, facility, admission, elder, incident, audit, role, account, organization, and platform permissions. See `modules/core/types.ts` and `modules/core/server/permissions.ts`.
|
||||
- The dashboard already aggregates elders, beds, admissions, care tasks, health reviews, and emergency incidents with permission checks. See `app/(app)/app/dashboard/page.tsx`.
|
||||
- Health currently has deterministic anomaly detection for vital records and creates health anomaly reviews from thresholds. See `modules/health/server/operations.ts`.
|
||||
- Alerting already has rule and trigger tables that can represent warnings and suggested handling. See `modules/alerts/server/operations.ts` and `modules/core/server/schema.ts`.
|
||||
- Existing elder/bed operational context can already attach permission-filtered care task, health review/vital, and incident lines to elders. See `modules/operations/server/context.ts`.
|
||||
- Health profile, vital, chronic condition, anomaly review, family contact, visit, feedback, and admission data exist but would need an AI-specific resident context assembler to gather one resident's full analysis input. See `modules/health/server/operations.ts`, `modules/family/server/operations.ts`, and `modules/core/server/operations.ts`.
|
||||
- API responses use `{ success, reason, ...payload }` and `Cache-Control: no-store`. See `modules/core/server/api.ts`.
|
||||
|
||||
## Requirements
|
||||
|
||||
- The AI module must preserve organization isolation: every retrieval, prompt context, generated analysis, and generated action draft must be scoped to the authenticated active organization unless the caller has a platform-level reason to cross scopes.
|
||||
- The AI module must preserve existing role permissions: analysis endpoints must require the same read permissions as the underlying data they inspect, and any write/action-producing workflow must require the matching manage permission.
|
||||
- MVP authorization must add dedicated AI and knowledge permissions while still applying underlying domain data permissions.
|
||||
- Dedicated MVP permission points should include `ai:read`, `ai:manage`, `knowledge:read`, and `knowledge:manage`.
|
||||
- Generating elder AI analysis must require `ai:read`, `elder:read`, an active organization, and only include optional resident-context data when the caller has the matching read permission such as `health:read`, `care:read`, `alert:read`, `family:read`, `admission:read`, `facility:read`, or `incident:read`.
|
||||
- Analysis history details must be filtered by stored `dataScopes` so users cannot view generated content derived from data families they cannot currently read.
|
||||
- Maintaining knowledge entries must require `knowledge:manage`; using retrieved knowledge in analysis must require `knowledge:read`.
|
||||
- Default role seeding should grant:
|
||||
- `platform_admin`: `ai:read`, `ai:manage`, `knowledge:read`, `knowledge:manage`.
|
||||
- `org_admin`: `ai:read`, `ai:manage`, `knowledge:read`, `knowledge:manage`.
|
||||
- `manager`: `ai:read`, `ai:manage`, `knowledge:read`, `knowledge:manage`.
|
||||
- `caregiver`: `ai:read`, `knowledge:read`.
|
||||
- `viewer`, `family`, and `resident`: no AI or knowledge permissions by default.
|
||||
- The first implementation should add a shared server-side AI boundary rather than scattering provider calls across feature modules.
|
||||
- The AI boundary must allow future provider/model changes without touching each product surface.
|
||||
- MVP AI orchestration must use LangChain as the primary server-side runtime for model calls, retrieval chains, agent/tool orchestration, and structured analysis output.
|
||||
- Vercel AI SDK should not be part of the MVP runtime path; keep it as a future option for conversational or streaming UI work.
|
||||
- MVP model access must use an OpenAI-compatible configurable provider interface with environment variables for base URL, API key, chat model, and embedding model.
|
||||
- The MVP UI must be a structured analysis panel attached to the elder profile/list workflow rather than a free-form chat assistant.
|
||||
- The MVP elder UI entry point must be an "AI 分析" action in each elder table row that opens a `wide` dialog panel.
|
||||
- MVP knowledge management UI must be available at `/settings/knowledge` with read access gated by `knowledge:read` and mutations gated by `knowledge:manage`.
|
||||
- The MVP analysis input must use the full available resident graph when the caller has matching read permissions.
|
||||
- MVP LangChain agent/tools must be read-only. They may load resident context, retrieve knowledge, and read analysis history, but must not provide mutation tools.
|
||||
- Knowledge retrieval must return source metadata that the UI can display or store with the analysis, so AI outputs are traceable to underlying records or documents.
|
||||
- MVP knowledge retrieval must store chunks and embeddings in PostgreSQL with pgvector, reusing the existing Drizzle/Postgres persistence boundary.
|
||||
- MVP knowledge ingestion must support manually maintained knowledge entries and server-side chunking/embedding on save.
|
||||
- MVP knowledge retrieval must include enabled platform shared knowledge plus enabled active-organization private knowledge, filtered by caller permissions.
|
||||
- AI analysis must be advisory by default. MVP output is limited to summaries, risk notes, recommendations, data gaps, and citations; future action-draft workflows require separate requirements and explicit user confirmation.
|
||||
- MVP elder AI analysis must only display structured recommendations. It must not create confirmable business drafts or one-click mutations for care tasks, alert triggers, health review notes, or other operational records.
|
||||
- MVP elder AI analyses must be saved as history records after generation.
|
||||
- MVP generation should run synchronously and save completed or failed history status.
|
||||
- Failed generation attempts must persist sanitized failed history and write audit logs.
|
||||
- Generated outputs must use structured schemas where the product needs machine-readable data, such as severity, confidence, citations, suggested next steps, or draft entity payloads.
|
||||
- MVP elder analysis output must use a fixed JSON-compatible schema with risk level, summary, findings, recommendations, data gaps, citations, confidence, and model summary.
|
||||
- AI calls must have observable failure handling: user-facing failures should be structured, and server logs/audit records should identify operation type, actor, organization, target, and result.
|
||||
|
||||
## Candidate Product Surfaces
|
||||
|
||||
- MVP: Elder profile analysis: summarize one resident's health notes, vitals, care tasks, alerts, admissions, and family feedback.
|
||||
- Dashboard executive summary: summarize current risk across care, health, beds, admissions, and incidents.
|
||||
- Health anomaly explanation: explain why a review matters and suggest follow-up questions or actions.
|
||||
- Alert and incident triage: summarize context, recommend severity/status, and draft handling notes.
|
||||
- Care operations assistant: answer operational questions from scoped data and draft care-task notes.
|
||||
- Knowledge-base Q&A: retrieve internal policies, care protocols, notices, facility SOPs, and relevant system records.
|
||||
|
||||
## Constraints
|
||||
|
||||
- Do not bypass deterministic rules already present in health anomaly detection and alert handling; AI should augment those flows first.
|
||||
- Do not introduce unscoped vector search that can leak data across organizations.
|
||||
- Do not introduce a separate vector database/service for the MVP.
|
||||
- Do not let AI-specific permissions bypass the underlying domain permissions for resident, health, care, family, alert, admission, facility, device, or incident data.
|
||||
- Do not show analysis history content to users who lack read permission for any stored `dataScopes` used by the analysis.
|
||||
- Do not expose organization-private knowledge to other organizations through platform shared retrieval.
|
||||
- Do not include file upload, document parsing, OCR, crawling, or external knowledge sync in the MVP.
|
||||
- Do not make knowledge maintenance API-only; MVP needs a user-facing settings page.
|
||||
- Do not store full prompts or sensitive resident data in third-party logs unless explicitly configured and reviewed.
|
||||
- Do not store full prompts, resident context, sensitive data, or raw provider errors in failed history records.
|
||||
- Do not hard-code a single model vendor into feature modules.
|
||||
- Do not treat generated AI analysis history as an authoritative clinical record; it is advisory operational support.
|
||||
- Do not add "one-click create" or confirmable draft business mutations from MVP AI analysis output.
|
||||
- Do not define mutation-capable LangChain tools in the MVP, even if they are not exposed in the UI.
|
||||
- Do not require frontend components to know provider-specific APIs.
|
||||
- Do not start implementation until `design.md` and `implement.md` exist and the user has approved the final planning artifacts.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] PRD identifies elder profile AI analysis as the MVP user workflow and fixed structured analysis panel as the MVP interaction.
|
||||
- [ ] Elder list rows expose an AI analysis action for authorized users and open a wide analysis dialog.
|
||||
- [ ] PRD defines the full resident graph as MVP data sources and identifies out-of-scope AI surfaces.
|
||||
- [ ] Technical design defines the AI server module boundary, provider/orchestration choice, RAG storage strategy, authorization model, source-citation contract, audit/logging contract, and fallback behavior.
|
||||
- [ ] MVP implementation uses LangChain as the server-side AI orchestration layer and does not introduce Vercel AI SDK runtime code.
|
||||
- [ ] MVP model configuration supports OpenAI-compatible `AI_BASE_URL`, `AI_API_KEY`, `AI_CHAT_MODEL`, and `AI_EMBEDDING_MODEL` style settings.
|
||||
- [ ] Implementation plan defines ordered steps, validation commands, risky files, migration needs, and rollback points.
|
||||
- [ ] Any implemented AI analysis endpoint checks authentication, active organization, and required permissions before loading data or retrieving knowledge.
|
||||
- [ ] MVP adds and seeds `ai:read`, `ai:manage`, `knowledge:read`, and `knowledge:manage` permission definitions and assigns them to appropriate default operational/admin roles.
|
||||
- [ ] Default role permission seeding matches the agreed AI/knowledge grants for platform admins, org admins, managers, caregivers, viewers, family users, and residents.
|
||||
- [ ] Elder analysis context only includes each optional data family when the caller has the matching domain read permission.
|
||||
- [ ] Analysis history records store `dataScopes`, and history detail visibility is denied or redacted when the current user lacks any required scope permission.
|
||||
- [ ] Any implemented retrieval mechanism stores and filters knowledge by organization scope and returns source metadata with each retrieval result.
|
||||
- [ ] MVP retrieval uses PostgreSQL + pgvector with Drizzle migrations and organization-scoped query filters.
|
||||
- [ ] MVP knowledge entries can be manually maintained and embedded into searchable chunks with source metadata.
|
||||
- [ ] `/settings/knowledge` exists for authorized users and supports list, filter, create, edit, enable/disable, and delete workflows.
|
||||
- [ ] Knowledge retrieval includes only enabled platform shared knowledge and enabled knowledge for the caller's active organization.
|
||||
- [ ] MVP AI analysis output contains recommendations only and does not create or persist business drafts/actions beyond the analysis history record itself.
|
||||
- [ ] MVP LangChain tools are read-only and cannot mutate care, health, alert, family, admission, facility, incident, or knowledge data.
|
||||
- [ ] MVP AI analysis responses and persisted history use the fixed structured output schema.
|
||||
- [ ] Generated elder analyses are persisted with actor, elder, organization, structured result, citation metadata, model summary, status, and timestamps.
|
||||
- [ ] Synchronous generation shows a loading state and returns structured API success/failure responses.
|
||||
- [ ] Failed generation attempts persist sanitized failed history records and audit logs without full prompts or raw sensitive context.
|
||||
- [ ] Quality verification includes `pnpm lint`, `pnpm type-check`, and targeted tests for permission scoping and structured failure behavior.
|
||||
|
||||
## Likely Out of Scope For MVP
|
||||
|
||||
- Fully autonomous agents that mutate production records without a user confirmation step.
|
||||
- Cross-organization analytics for ordinary organization users.
|
||||
- Replacing existing deterministic anomaly rules with AI-only decisions.
|
||||
- Conversational AI/chat UX for MVP elder analysis.
|
||||
- Real-time streaming chat across the whole product.
|
||||
- Async generation jobs, background workers, polling, and retry queues.
|
||||
- Building a full document-management system before the minimum knowledge-ingestion path is defined.
|
||||
- PDF/Word upload, OCR, web crawling, and external-system knowledge synchronization.
|
||||
26
.trellis/tasks/07-04-ai-agent-knowledge-analysis/task.json
Normal file
26
.trellis/tasks/07-04-ai-agent-knowledge-analysis/task.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "ai-agent-knowledge-analysis",
|
||||
"name": "ai-agent-knowledge-analysis",
|
||||
"title": "AI agent knowledge analysis",
|
||||
"description": "",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": null,
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "TalexDreamSoul",
|
||||
"assignee": "TalexDreamSoul",
|
||||
"createdAt": "2026-07-04",
|
||||
"completedAt": null,
|
||||
"branch": null,
|
||||
"base_branch": "main",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [],
|
||||
"notes": "",
|
||||
"meta": {}
|
||||
}
|
||||
Reference in New Issue
Block a user