Skip to content
reaatechREAATECH

Files · AWS Bedrock Knowledge Agent for AppFolio Tenant Inquiries

80 (1 binary, 634.1 kB total)attempt 1

README.md·5824 B·markdown
markdown
# AWS Bedrock Knowledge Agent for AppFolio Tenant Inquiries
 
> A self-service AI knowledge base that answers tenant questions about policies, maintenance, and lease terms using AppFolio data — powered by Amazon Bedrock Claude and hybrid RAG search.
 
Property managers field dozens of repetitive tenant questions daily — lease terms, pet policies, maintenance requests, rent due dates. This project automates those answers with accurate, citation-backed responses by indexing AppFolio documents into a hybrid vector/keyword search engine and retrieving relevant context before generating responses via Bedrock Claude.
 
## Architecture
 
```
AppFolio documents → Ingestion Pipeline → Qdrant vector store → Chat API → Bedrock Claude → Answer with citations
```
 
The ingestion pipeline pulls lease agreements, property rules, and FAQs from AppFolio, chunks them into passages, generates embeddings via Voyage AI, and upserts them into Qdrant. At query time, the chat endpoint embeds the question, performs hybrid vector + keyword search, fuses results by reciprocal rank fusion, augments a system prompt with retrieved context, generates a response via Bedrock Claude, and returns citations alongside the answer.
 
## Quick Start
 
```bash
pnpm install
cp .env.example .env     # edit with your credentials
pnpm dev                 # starts Next.js on http://localhost:3000
```
 
Check health:
 
```bash
curl http://localhost:3000/api/health
```
 
## API
 
### `POST /api/chat`
 
**Request body:**
```json
{
  "message": "When is my rent due?",
  "tenantId": "t-123",
  "sessionId": "s-abc"
}
```
 
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `message` | `string` | yes | Tenant question (1-2000 chars) |
| `tenantId` | `string` | no | AppFolio tenant ID for personalized context |
| `sessionId` | `string` | no | Session identifier for conversation tracking |
 
**Response (200):**
```json
{
  "answer": "Your rent is due on the 1st of each month...",
  "citations": [
    { "documentId": "lease-001", "chunkId": "lease-001-0", "content": "...", "score": 0.95 }
  ],
  "usage": { "inputTokens": 150, "outputTokens": 45 },
  "metadata": { "model": "anthropic.claude-sonnet-4-v1:0", "retrievalCount": 3, "timestamp": "2025-01-01T00:00:00Z" }
}
```
 
**Error (400):** `{ "error": "Invalid request", "details": [...] }`
 
**Error (500):** `{ "error": "Query failed", "message": "..." }`
 
### `GET /api/health`
 
**Response (200):**
```json
{
  "status": "ok",
  "checks": { "qdrant": "ok", "bedrock": "ok" },
  "uptime": 123.45,
  "version": "0.1.0"
}
```
 
**Response (503 — degraded):** Same shape with `"status": "degraded"` and any failing check set to `"error"`.
 
## Tech Stack
 
| Package | Version | Role |
|---------|---------|------|
| `next` | 16.2.6 | App framework with App Router |
| `react` | 19.2.4 | UI rendering |
| `@aws-sdk/client-bedrock-runtime` | 3.1053.0 | Bedrock Claude invocations |
| `@aws-sdk/client-bedrock-agent-runtime` | 3.1053.0 | Bedrock Agents runtime |
| `@qdrant/js-client-rest` | 1.18.0 | Qdrant vector store client |
| `voyageai` | 0.2.1 | Embedding generation |
| `zod` | 4.4.3 | Schema validation |
| `p-limit` | 7.3.0 | Embedding concurrency limiting |
| `p-retry` | 8.0.0 | Retry logic for Qdrant calls |
| `langfuse` | 3.38.20 | Observability and tracing |
| `@reaatech/hybrid-rag` | 0.1.0 | Core RAG types and schemas |
| `@reaatech/hybrid-rag-embedding` | 0.1.0 | Embedding service base class |
| `@reaatech/hybrid-rag-evaluation` | 0.1.0 | Retrieval evaluation and benchmarking |
| `@reaatech/agent-budget-engine` | 0.1.0 | LLM budget enforcement |
| `@reaatech/agent-eval-harness-golden` | 0.1.0 | Golden trajectory regression testing |
 
## Evaluation
 
### Retrieval evaluation
 
Uses `@reaatech/hybrid-rag-evaluation` to compute standard IR metrics — Precision@K, Recall@K, NDCG@K, MAP, MRR — against a dataset of sample queries with known relevant documents. Latency benchmarking measures P50/P90/P99 response times.
 
```bash
# Programmatic usage
import { runRetrievalEval } from "./src/eval/retrieval.js";
await runRetrievalEval(pipeline);
```
 
### Golden trajectory testing
 
Uses `@reaatech/agent-eval-harness-golden` to compare generated answers against curated golden trajectories for common tenant questions (rent due, maintenance requests, pet policy, ticket status). Detects regressions when responses diverge from expected quality.
 
```bash
import { runGoldenEvalSuite } from "./src/eval/golden.js";
const results = await runGoldenEvalSuite();
```
 
## Project Layout
 
```
app/                  Next.js App Router — API routes (chat, health) + page
src/
  config/             Zod-validated environment config
  types/              Shared domain types (TenantContext, ChatResponse, etc.)
  appfolio/           AppFolio HTTP API client
  llm/                Bedrock Claude wrapper (generate, stream, pricing)
  rag/
    embedding.ts      Voyage AI embedding service (extends @reaatech/hybrid-rag-embedding)
    vector-store.ts   Qdrant adapter with hybrid search
    ingestion.ts      Full ingestion pipeline (pull → chunk → embed → upsert)
    pipeline.ts       RAG query pipeline (embed → search → check → generate → cite)
  budget/
    store.ts          In-memory spend tracker
    pricing.ts        Model cost estimation
    controller.ts     Budget enforcement via @reaatech/agent-budget-engine
  eval/
    retrieval.ts      IR metric evaluation and latency benchmarking
    golden.ts         Golden trajectory regression testing
  observability/      Langfuse-compatible logging and tracing
  index.ts            Public API entry point
tests/                Vitest suite (mirrors src/ and app/)
packages/             API reference docs for every dependency
```
 
## License
 
MIT — see [LICENSE](./LICENSE).