Skip to main content
Glama
README.md
# GenAI Lab

**GenAI Lab** is a TypeScript playground for building controlled GenAI workflows with:

- Retrieval-Augmented Generation (RAG) over a local knowledge base
- LangGraph-based agent planning and routing
- MCP (Model Context Protocol) tools/resources/prompts
- bounded, safe fallback behavior

It is intentionally compact so the mechanics stay inspectable end-to-end.

---

## Neat project description

GenAI Lab demonstrates a practical pattern for safe AI agents: it separates **decision (LLM-planned routing)** from **execution (typed nodes for retrieval, drafting, answering, and finalization)**, and exposes the same core capabilities through a direct CLI and an MCP server interface.

---

## What the project includes

- `agent` flow (LangGraph)
  - plans a response path based on a user request
  - retrieves notes when needed
  - drafts a message or answers a question from retrieved context
  - retries retrieval once when first pass yields insufficient context
  - returns deterministic fallback responses when appropriate

- RAG utilities
  - local semantic search over notes using OpenAI embeddings
  - source-grounded answers with `[note_x]` citations

- MCP surface
  - `search_notes` tool
  - `answer_from_notes` tool
  - `notes://all` resource
  - `rag_answer_prompt` prompt template

---

## Repository layout

```text
lib/
  agent/
    agent-state.ts      # LangGraph state schema
    mini-agent.ts       # LangGraph graph + nodes + routing
  embedding.ts          # Embedding helpers
  knowledge-base.ts     # In-memory note dataset
  rag-types.ts          # Shared RAG types
  retrieve-context.ts   # Retrieval filtering/threshold flow
  rag-answer.ts         # Standalone RAG answer generation
  semantic-search.ts    # Embedding + cosine similarity search
  vector-utils.ts       # Cosine similarity implementation

mcp/
  server.ts            # MCP server + tools/resources/prompts
  client-test.ts       # Script to test server tools/resources/prompts
  llm-client-test.ts   # Script showing LLM tool selection via MCP

scripts/
  agent.ts             # Run the LangGraph mini agent
  rag.ts               # Run standalone RAG answer flow
  semantic-search.ts    # Run semantic search directly
```

---

## Setup

Requirements:

- Node.js 18+
- `pnpm`

```bash
pnpm install
```

Create `.env.local` at the repository root:

```bash
OPENAI_API_KEY=your_openai_api_key
```

Both completion and embedding calls use OpenAI:

- `gpt-4.1-mini` for planning/answering/drafting
- `text-embedding-3-small` for semantic search

---

## Usage

### Run the mini agent

```bash
pnpm agent "Can you explain why retrieval should happen before generation?"
```

Output includes the full final state and `finalResponse`.

### Run standalone RAG

```bash
pnpm rag "Why do long chats become more expensive?"
```

### Run semantic search

```bash
pnpm semantic-search "backend tool execution"
```

### Start MCP server

```bash
pnpm mcp:server
```

Runs over stdio and exposes tools/resources/prompts defined in `mcp/server.ts`.

### MCP integration checks

```bash
pnpm mcp:test        # raw tool/resource/prompt client checks
pnpm mcp:llm         # LLM-driven MCP tool-calling demo
```

---

## How the agent flow works

1. **Planner (`planner`)**: maps request intent into an execution plan (`retrieve_notes`, `answer_question`, `draft_message`, `final_response`).
2. **Retrieve (`retrieveNotes`)**: runs similarity retrieval when required.
3. **Draft/Answer (`draftMessage` / `answerQuestion`)**:
   - drafts a Slack-style message
   - or answers using only retrieved notes, with citations
4. **Retry policy**:
   - if first retrieval is empty and this is the first attempt, retry once with a broader query and lower threshold
5. **Finalize (`finalize`)**: returns drafted output, RAG answer, retrieved context, or a bounded fallback.

The state machine is intentionally explicit and inspectable:

```text
START -> planner
  ├─> retrieveNotes -> answerQuestion -> finalize
  ├─> retrieveNotes -> draftMessage -> finalize
  ├─> draftMessage -> finalize
  └─> finalize
```

---

## Design principles implemented

- **Controlled output quality**: tool use and response style are constrained by explicit system prompts.
- **No side-effect leakage**: the planner only decides plan, all actions are backend nodes.
- **Source grounding**: answers can cite only known sources (`[note_#]`).
- **Bounded behavior**: retries are limited and unsupported requests take a safe fallback path.

---

## Notes on MCP and agent parity

The LangGraph flow and MCP tools use the same underlying retrieval/RAG primitives:

- semantic search logic lives in `lib/semantic-search.ts`
- answer generation logic lives in `lib/rag-answer.ts`
- note store is shared in `lib/knowledge-base.ts`

This allows you to compare:

- in-repo agent orchestration (`pnpm agent`)
- direct function style RAG (`pnpm rag`)
- tool-based orchestration (`pnpm mcp:llm`)

---

## Future improvements

- Persist notes in a real vector database
- Add chunking and richer document metadata
- Add confidence thresholds + eval snapshots
- Add contract tests for planner routing and retrieval fallback

---

## Quality checklist

- `pnpm typecheck` validates strict TypeScript compilation.
- `pnpm format` formats all files with Prettier.