factq 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- factq-0.1.0/.github/workflows/ci.yml +75 -0
- factq-0.1.0/.gitignore +35 -0
- factq-0.1.0/CLAUDE.md +159 -0
- factq-0.1.0/PKG-INFO +101 -0
- factq-0.1.0/README.md +71 -0
- factq-0.1.0/docs/ARCHITECTURE.md +101 -0
- factq-0.1.0/docs/adr/001-rlm-over-rag.md +35 -0
- factq-0.1.0/docs/adr/README.md +13 -0
- factq-0.1.0/docs/adr/TEMPLATE.md +17 -0
- factq-0.1.0/pyproject.toml +85 -0
- factq-0.1.0/src/factq/__init__.py +3 -0
- factq-0.1.0/src/factq/cli.py +38 -0
- factq-0.1.0/src/factq/py.typed +0 -0
- factq-0.1.0/tests/__init__.py +0 -0
- factq-0.1.0/tests/conftest.py +3 -0
- factq-0.1.0/tests/test_cli.py +35 -0
- factq-0.1.0/uv.lock +1116 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main]
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
quality-gates:
|
|
19
|
+
name: Quality Gates
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Install uv
|
|
26
|
+
uses: astral-sh/setup-uv@v4
|
|
27
|
+
with:
|
|
28
|
+
enable-cache: true
|
|
29
|
+
|
|
30
|
+
- name: Set up Python
|
|
31
|
+
run: uv python install 3.12
|
|
32
|
+
|
|
33
|
+
- name: Install dependencies
|
|
34
|
+
run: uv sync --locked
|
|
35
|
+
|
|
36
|
+
- name: Lint (ruff)
|
|
37
|
+
run: uv run ruff check src/ tests/
|
|
38
|
+
|
|
39
|
+
- name: Type check (mypy)
|
|
40
|
+
run: uv run mypy src/
|
|
41
|
+
|
|
42
|
+
- name: Test (pytest)
|
|
43
|
+
run: uv run pytest tests/ -v --cov=src --cov-report=term-missing
|
|
44
|
+
|
|
45
|
+
publish:
|
|
46
|
+
name: Publish to PyPI
|
|
47
|
+
needs: quality-gates
|
|
48
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
|
|
51
|
+
permissions:
|
|
52
|
+
contents: read
|
|
53
|
+
id-token: write
|
|
54
|
+
|
|
55
|
+
environment:
|
|
56
|
+
name: pypi
|
|
57
|
+
url: https://pypi.org/project/factq/
|
|
58
|
+
|
|
59
|
+
steps:
|
|
60
|
+
- name: Checkout
|
|
61
|
+
uses: actions/checkout@v4
|
|
62
|
+
|
|
63
|
+
- name: Install uv
|
|
64
|
+
uses: astral-sh/setup-uv@v4
|
|
65
|
+
with:
|
|
66
|
+
enable-cache: true
|
|
67
|
+
|
|
68
|
+
- name: Set up Python
|
|
69
|
+
run: uv python install 3.12
|
|
70
|
+
|
|
71
|
+
- name: Build package
|
|
72
|
+
run: uv build
|
|
73
|
+
|
|
74
|
+
- name: Publish to PyPI
|
|
75
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
factq-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.egg-info/
|
|
6
|
+
*.egg
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.whl
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.venv/
|
|
13
|
+
.python-version
|
|
14
|
+
|
|
15
|
+
# Testing & coverage
|
|
16
|
+
.pytest_cache/
|
|
17
|
+
.coverage
|
|
18
|
+
htmlcov/
|
|
19
|
+
.mypy_cache/
|
|
20
|
+
|
|
21
|
+
# OS
|
|
22
|
+
.DS_Store
|
|
23
|
+
Thumbs.db
|
|
24
|
+
|
|
25
|
+
# IDE
|
|
26
|
+
.idea/
|
|
27
|
+
.vscode/
|
|
28
|
+
*.swp
|
|
29
|
+
*.swo
|
|
30
|
+
*~
|
|
31
|
+
|
|
32
|
+
# Secrets & env
|
|
33
|
+
.env
|
|
34
|
+
.env.*
|
|
35
|
+
!.env.example
|
factq-0.1.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code when working on the factq CLI project.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
**factq** — Your LLM's Local Source of Truth. A local-first knowledge base and verification engine. Python library + CLI + MCP server. Distributed via PyPI (`pip install factq`).
|
|
8
|
+
|
|
9
|
+
**Key interfaces:** CLI (`factq`), Python library (`import factq`), MCP server (planned).
|
|
10
|
+
|
|
11
|
+
## Quick Reference
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Quality gates (run before completing any task)
|
|
15
|
+
uv run ruff check src/ tests/ # Lint (auto-fix: --fix)
|
|
16
|
+
uv run mypy src/ # Type check (strict)
|
|
17
|
+
uv run pytest tests/ -v # Tests
|
|
18
|
+
|
|
19
|
+
# All quality gates at once
|
|
20
|
+
uv run ruff check src/ tests/ && uv run mypy src/ && uv run pytest tests/ -v
|
|
21
|
+
|
|
22
|
+
# CLI testing
|
|
23
|
+
uv run factq --version
|
|
24
|
+
uv run factq init
|
|
25
|
+
uv run factq query "test question"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Architecture
|
|
29
|
+
|
|
30
|
+
See `docs/ARCHITECTURE.md` for full details.
|
|
31
|
+
|
|
32
|
+
### Resolution Pipeline
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Query → KB Lookup (docs/ folder, milliseconds)
|
|
36
|
+
→ Deepthink (LLM writes Python to verify, sandbox execution, up to 5 iterations)
|
|
37
|
+
→ Commit (verified fact saved back to docs/, git-versioned)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Project Structure
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
factq-cli/
|
|
44
|
+
├── src/factq/ # Core package (hatchling, src layout)
|
|
45
|
+
│ ├── __init__.py # Package root, version
|
|
46
|
+
│ ├── cli.py # Click CLI entry point
|
|
47
|
+
│ └── py.typed # PEP 561 type stub marker
|
|
48
|
+
├── tests/ # Pytest test suite
|
|
49
|
+
├── docs/ # Project documentation
|
|
50
|
+
│ ├── ARCHITECTURE.md # Technical architecture
|
|
51
|
+
│ └── adr/ # Architecture Decision Records
|
|
52
|
+
├── pyproject.toml # Project config (Python 3.12+, Apache-2.0)
|
|
53
|
+
└── CLAUDE.md # This file
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Key Dependencies
|
|
57
|
+
|
|
58
|
+
| Tool | Purpose |
|
|
59
|
+
|------|---------|
|
|
60
|
+
| **uv** | Package manager, venv (Python 3.12) |
|
|
61
|
+
| **hatchling** | Build backend |
|
|
62
|
+
| **click** | CLI framework |
|
|
63
|
+
| **rich** | Terminal formatting |
|
|
64
|
+
| **pydantic** | Data models |
|
|
65
|
+
| **ruff** | Linter |
|
|
66
|
+
| **mypy** | Type checker (strict mode) |
|
|
67
|
+
| **pytest** | Test runner |
|
|
68
|
+
|
|
69
|
+
## Common Commands
|
|
70
|
+
|
|
71
|
+
Always use `uv run python` or `uv run pytest` — never bare `python` or `pytest`.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Install dependencies
|
|
75
|
+
uv sync
|
|
76
|
+
|
|
77
|
+
# Lint
|
|
78
|
+
uv run ruff check src/ tests/
|
|
79
|
+
|
|
80
|
+
# Type check
|
|
81
|
+
uv run mypy src/
|
|
82
|
+
|
|
83
|
+
# Run tests
|
|
84
|
+
uv run pytest tests/ -v
|
|
85
|
+
|
|
86
|
+
# Run tests with coverage
|
|
87
|
+
uv run pytest tests/ -v --cov=src --cov-report=term-missing
|
|
88
|
+
|
|
89
|
+
# Build package
|
|
90
|
+
uv run python -m build
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Quality Gates
|
|
94
|
+
|
|
95
|
+
**All must pass before task completion:**
|
|
96
|
+
|
|
97
|
+
| Gate | Command | Requirement |
|
|
98
|
+
|------|---------|-------------|
|
|
99
|
+
| Lint | `uv run ruff check src/ tests/` | Zero errors |
|
|
100
|
+
| Types | `uv run mypy src/` | Zero errors |
|
|
101
|
+
| Tests | `uv run pytest tests/ -v` | All pass |
|
|
102
|
+
|
|
103
|
+
**If any fail, you are NOT DONE.**
|
|
104
|
+
|
|
105
|
+
## Code Style & Conventions
|
|
106
|
+
|
|
107
|
+
- **Python 3.12+**, line length 100
|
|
108
|
+
- Type annotations required on all functions (mypy strict)
|
|
109
|
+
- Ruff rules: `E, F, I, N, UP, B, SIM, TCH`
|
|
110
|
+
- License: Apache-2.0
|
|
111
|
+
- Only add dependencies with permissive licenses (Apache 2.0, MIT, BSD)
|
|
112
|
+
|
|
113
|
+
### Python Conventions
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from __future__ import annotations # 1. Future
|
|
117
|
+
import sys # 2. Stdlib
|
|
118
|
+
from pydantic import BaseModel # 3. Third-party
|
|
119
|
+
from factq.core import Engine # 4. Local
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
- Classes: `PascalCase` | Functions/variables: `snake_case` | Constants: `UPPER_SNAKE_CASE`
|
|
123
|
+
- Prefer `list[str]` over `List[str]`, `str | None` over `Optional[str]`
|
|
124
|
+
- Commit format: `<type>: <description>` (feat/fix/test/refactor/docs/chore)
|
|
125
|
+
|
|
126
|
+
## Development Principles
|
|
127
|
+
|
|
128
|
+
### Red / Green / Refactor — MANDATORY
|
|
129
|
+
|
|
130
|
+
| Phase | Action |
|
|
131
|
+
|-------|--------|
|
|
132
|
+
| RED | Write failing test first |
|
|
133
|
+
| GREEN | Minimal code to pass |
|
|
134
|
+
| REFACTOR | Clean up, tests stay green |
|
|
135
|
+
|
|
136
|
+
### SOLID
|
|
137
|
+
|
|
138
|
+
| Principle | Rule |
|
|
139
|
+
|-----------|------|
|
|
140
|
+
| **S**ingle Responsibility | One class, one job |
|
|
141
|
+
| **O**pen/Closed | Extend via composition |
|
|
142
|
+
| **L**iskov Substitution | Subtypes honor contracts |
|
|
143
|
+
| **I**nterface Segregation | Focused interfaces |
|
|
144
|
+
| **D**ependency Inversion | Depend on abstractions |
|
|
145
|
+
|
|
146
|
+
## Git Rules
|
|
147
|
+
|
|
148
|
+
- NEVER commit without explicit user request
|
|
149
|
+
- NEVER add Co-Authored-By lines
|
|
150
|
+
- NEVER amend unless explicitly asked
|
|
151
|
+
- Stage specific files, not `git add -A`
|
|
152
|
+
|
|
153
|
+
## Key Documents
|
|
154
|
+
|
|
155
|
+
| Document | Purpose |
|
|
156
|
+
|----------|---------|
|
|
157
|
+
| `docs/ARCHITECTURE.md` | Technical architecture and component design |
|
|
158
|
+
| `docs/adr/` | Architecture Decision Records |
|
|
159
|
+
| `docs/adr/001-rlm-over-rag.md` | Why RLM over RAG |
|
factq-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: factq
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Your LLM's Local Source of Truth — a local-first knowledge base and verification engine for hallucination prevention.
|
|
5
|
+
Project-URL: Homepage, https://factq.dev
|
|
6
|
+
Project-URL: Documentation, https://factq.dev
|
|
7
|
+
Project-URL: Repository, https://github.com/factq-dev/factq-cli
|
|
8
|
+
Project-URL: Issues, https://github.com/factq-dev/factq-cli/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/factq-dev/factq-cli/blob/main/CHANGELOG.md
|
|
10
|
+
Author: FactQ Team
|
|
11
|
+
License: Apache-2.0
|
|
12
|
+
Keywords: factuality,hallucination,knowledge-base,llm,mcp,rlm,verification
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Requires-Dist: click>=8.1
|
|
24
|
+
Requires-Dist: pydantic>=2.0
|
|
25
|
+
Requires-Dist: pyyaml>=6.0
|
|
26
|
+
Requires-Dist: rich>=13.0
|
|
27
|
+
Provides-Extra: mcp
|
|
28
|
+
Requires-Dist: mcp>=1.0; extra == 'mcp'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# factq
|
|
32
|
+
|
|
33
|
+
**Your LLM's Local Source of Truth**
|
|
34
|
+
|
|
35
|
+
A local-first knowledge base and verification engine that sits between you and your AI tools. It answers from proven knowledge first, validates through executable code when needed, and gets smarter with every query.
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install factq
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import factq
|
|
47
|
+
|
|
48
|
+
# Initialize from project root — auto-indexes docs/ folder
|
|
49
|
+
fq = factq.init(".")
|
|
50
|
+
|
|
51
|
+
# Query checks project docs first, then KB, then Deepthink
|
|
52
|
+
result = fq.query("What version of Pydantic does our project use?")
|
|
53
|
+
# result.source: 'docs' | 'kb' | 'deepthink'
|
|
54
|
+
|
|
55
|
+
# Save a verified finding to the project's docs/ folder
|
|
56
|
+
fq.save("docs/research/pydantic_v2_migration.md", result)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Or from the CLI:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
factq init # index current project
|
|
63
|
+
factq query "What is our database schema?" # docs-first resolution
|
|
64
|
+
factq save docs/research/schema_notes.md # commit a finding
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## How It Works
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Query → KB Lookup (docs/ folder, milliseconds)
|
|
71
|
+
→ Deepthink (LLM writes Python to verify, sandbox execution)
|
|
72
|
+
→ Commit (verified fact saved back to docs/, git-versioned)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
1. **Docs-First Resolution** — Your project's `docs/` folder is the first source of truth
|
|
76
|
+
2. **Executable Verification** — When docs can't answer, factq writes and runs Python code to verify facts in a secure sandbox
|
|
77
|
+
3. **Self-Growing Knowledge** — Verified facts are saved back as markdown files, version-controlled in git
|
|
78
|
+
4. **MCP Server** — Runs as a local MCP server for Claude Code, Cursor, and Windsurf
|
|
79
|
+
|
|
80
|
+
## Why factq?
|
|
81
|
+
|
|
82
|
+
| | Traditional RAG | Cloud Search | **factq** |
|
|
83
|
+
|---|---|---|---|
|
|
84
|
+
| **Verification** | Text similarity | Citation links | Executable code proof |
|
|
85
|
+
| **Infrastructure** | 3-6 GB VRAM | Cloud API | Zero VRAM, ~28 MB |
|
|
86
|
+
| **Knowledge Persistence** | Ephemeral chunks | None | Git-versioned docs/ |
|
|
87
|
+
| **Offline** | Partial | No | **Fully offline** |
|
|
88
|
+
| **Gets Smarter Over Time** | No | No | **Yes** |
|
|
89
|
+
|
|
90
|
+
## Development
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
git clone https://github.com/factq-dev/factq-cli.git
|
|
94
|
+
cd factq-cli
|
|
95
|
+
uv sync
|
|
96
|
+
uv run pytest tests/ -v
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## License
|
|
100
|
+
|
|
101
|
+
Apache-2.0
|
factq-0.1.0/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# factq
|
|
2
|
+
|
|
3
|
+
**Your LLM's Local Source of Truth**
|
|
4
|
+
|
|
5
|
+
A local-first knowledge base and verification engine that sits between you and your AI tools. It answers from proven knowledge first, validates through executable code when needed, and gets smarter with every query.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install factq
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import factq
|
|
17
|
+
|
|
18
|
+
# Initialize from project root — auto-indexes docs/ folder
|
|
19
|
+
fq = factq.init(".")
|
|
20
|
+
|
|
21
|
+
# Query checks project docs first, then KB, then Deepthink
|
|
22
|
+
result = fq.query("What version of Pydantic does our project use?")
|
|
23
|
+
# result.source: 'docs' | 'kb' | 'deepthink'
|
|
24
|
+
|
|
25
|
+
# Save a verified finding to the project's docs/ folder
|
|
26
|
+
fq.save("docs/research/pydantic_v2_migration.md", result)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or from the CLI:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
factq init # index current project
|
|
33
|
+
factq query "What is our database schema?" # docs-first resolution
|
|
34
|
+
factq save docs/research/schema_notes.md # commit a finding
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## How It Works
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Query → KB Lookup (docs/ folder, milliseconds)
|
|
41
|
+
→ Deepthink (LLM writes Python to verify, sandbox execution)
|
|
42
|
+
→ Commit (verified fact saved back to docs/, git-versioned)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
1. **Docs-First Resolution** — Your project's `docs/` folder is the first source of truth
|
|
46
|
+
2. **Executable Verification** — When docs can't answer, factq writes and runs Python code to verify facts in a secure sandbox
|
|
47
|
+
3. **Self-Growing Knowledge** — Verified facts are saved back as markdown files, version-controlled in git
|
|
48
|
+
4. **MCP Server** — Runs as a local MCP server for Claude Code, Cursor, and Windsurf
|
|
49
|
+
|
|
50
|
+
## Why factq?
|
|
51
|
+
|
|
52
|
+
| | Traditional RAG | Cloud Search | **factq** |
|
|
53
|
+
|---|---|---|---|
|
|
54
|
+
| **Verification** | Text similarity | Citation links | Executable code proof |
|
|
55
|
+
| **Infrastructure** | 3-6 GB VRAM | Cloud API | Zero VRAM, ~28 MB |
|
|
56
|
+
| **Knowledge Persistence** | Ephemeral chunks | None | Git-versioned docs/ |
|
|
57
|
+
| **Offline** | Partial | No | **Fully offline** |
|
|
58
|
+
| **Gets Smarter Over Time** | No | No | **Yes** |
|
|
59
|
+
|
|
60
|
+
## Development
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
git clone https://github.com/factq-dev/factq-cli.git
|
|
64
|
+
cd factq-cli
|
|
65
|
+
uv sync
|
|
66
|
+
uv run pytest tests/ -v
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## License
|
|
70
|
+
|
|
71
|
+
Apache-2.0
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
factq is a local-first knowledge base and verification engine. It intercepts LLM queries, resolves them against proven local knowledge, and falls back to executable verification when the knowledge base cannot answer.
|
|
6
|
+
|
|
7
|
+
## Resolution Pipeline
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
User Query
|
|
11
|
+
│
|
|
12
|
+
▼
|
|
13
|
+
┌─────────────────┐
|
|
14
|
+
│ Phase 0: KB │ Check docs/ folder and indexed knowledge base
|
|
15
|
+
│ Lookup │ Returns in milliseconds if found
|
|
16
|
+
└────────┬────────┘
|
|
17
|
+
│ miss
|
|
18
|
+
▼
|
|
19
|
+
┌─────────────────┐
|
|
20
|
+
│ Phase 1: │ LLM generates Python code to retrieve
|
|
21
|
+
│ Generate │ and verify the fact from external sources
|
|
22
|
+
└────────┬────────┘
|
|
23
|
+
│
|
|
24
|
+
▼
|
|
25
|
+
┌─────────────────┐
|
|
26
|
+
│ Phase 2: │ Code runs in sandbox. Errors trigger
|
|
27
|
+
│ Validate │ self-correction. Up to 5 iterations.
|
|
28
|
+
└────────┬────────┘
|
|
29
|
+
│ verified
|
|
30
|
+
▼
|
|
31
|
+
┌─────────────────┐
|
|
32
|
+
│ Phase 3: │ Verified result offered for commit
|
|
33
|
+
│ Commit │ to docs/. KB grows with every query.
|
|
34
|
+
└─────────────────┘
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Component Architecture
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
factq/
|
|
41
|
+
├── cli.py # Click CLI entry point
|
|
42
|
+
├── core/
|
|
43
|
+
│ ├── engine.py # Query orchestrator (KB → Deepthink → Commit)
|
|
44
|
+
│ ├── kb.py # Knowledge base: indexing, search, persistence
|
|
45
|
+
│ └── result.py # Query result model (answer, source, confidence)
|
|
46
|
+
├── deepthink/
|
|
47
|
+
│ ├── generator.py # Code generation for fact verification
|
|
48
|
+
│ ├── sandbox.py # Secure execution environment
|
|
49
|
+
│ └── validator.py # Output validation and retry logic
|
|
50
|
+
├── indexer/
|
|
51
|
+
│ ├── markdown.py # Markdown file parser and indexer
|
|
52
|
+
│ └── store.py # Index storage (local SQLite or flat files)
|
|
53
|
+
├── mcp/
|
|
54
|
+
│ └── server.py # MCP server for Claude Code, Cursor, Windsurf
|
|
55
|
+
└── adapters/
|
|
56
|
+
└── llm.py # LLM backend abstraction (local, API)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Key Design Decisions
|
|
60
|
+
|
|
61
|
+
### RLM Over RAG
|
|
62
|
+
|
|
63
|
+
factq uses the Recursive Language Model paradigm instead of traditional RAG. The LLM writes code to navigate and verify knowledge rather than relying on embedding-based similarity search. This eliminates 3-6 GB of VRAM overhead from embedding models and vector databases.
|
|
64
|
+
|
|
65
|
+
### Local-First
|
|
66
|
+
|
|
67
|
+
All data stays on the user's machine. The knowledge base is plain markdown files in `docs/`, version-controlled in git. No cloud dependency, no API keys required for core functionality.
|
|
68
|
+
|
|
69
|
+
### Sandbox Security
|
|
70
|
+
|
|
71
|
+
Five-layer defense-in-depth for Deepthink code execution:
|
|
72
|
+
1. Safe builtins (restricted Python runtime)
|
|
73
|
+
2. AST validation (block dangerous constructs)
|
|
74
|
+
3. Function whitelisting (approved stdlib only)
|
|
75
|
+
4. Execution timeouts (hard kill after N seconds)
|
|
76
|
+
5. Output truncation (prevent memory exhaustion)
|
|
77
|
+
|
|
78
|
+
### MCP Integration
|
|
79
|
+
|
|
80
|
+
factq runs as a local MCP server so AI coding tools can call `factq.query()` as a tool. The MCP interface is a thin wrapper around the core engine.
|
|
81
|
+
|
|
82
|
+
## Data Flow
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
docs/ folder (markdown) ──┐
|
|
86
|
+
├──► KB Index ──► Query Engine ──► Result
|
|
87
|
+
External sources ─────────┘ ▲ │
|
|
88
|
+
│ ▼
|
|
89
|
+
Deepthink ◄──── Sandbox
|
|
90
|
+
(generate) (execute)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Dependencies
|
|
94
|
+
|
|
95
|
+
| Layer | Dependencies | Rationale |
|
|
96
|
+
|-------|-------------|-----------|
|
|
97
|
+
| Core | pydantic, pyyaml | Data models, config |
|
|
98
|
+
| CLI | click, rich | Terminal interface |
|
|
99
|
+
| Deepthink | (stdlib only) | Sandbox uses restricted Python |
|
|
100
|
+
| MCP | mcp (optional) | Protocol server |
|
|
101
|
+
| LLM | (pluggable) | Adapter pattern for backends |
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# ADR-001: Use RLM Over RAG for Knowledge Retrieval
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Traditional RAG (Retrieval-Augmented Generation) requires embedding models (3-6 GB VRAM), vector databases, and chunk-based similarity search. This creates significant infrastructure overhead and produces results based on text similarity rather than verified truth.
|
|
10
|
+
|
|
11
|
+
The Recursive Language Model (RLM) paradigm (Zhang, Kraska, Khattab 2025) treats knowledge as variables to be explored programmatically. Instead of embedding and retrieving chunks, the LLM writes code to navigate, read, and cross-reference knowledge sources.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
factq uses RLM instead of RAG for knowledge retrieval and verification. The LLM generates Python code to:
|
|
16
|
+
|
|
17
|
+
1. Navigate the knowledge base structure
|
|
18
|
+
2. Read and parse relevant documents
|
|
19
|
+
3. Cross-reference multiple sources
|
|
20
|
+
4. Verify facts through executable code
|
|
21
|
+
|
|
22
|
+
Code execution happens in a sandboxed environment with five layers of security.
|
|
23
|
+
|
|
24
|
+
## Consequences
|
|
25
|
+
|
|
26
|
+
**Easier:**
|
|
27
|
+
- Zero VRAM overhead (no embedding models or vector databases)
|
|
28
|
+
- Deterministic verification (code either produces the answer or fails)
|
|
29
|
+
- Handles dependency chains that similarity search cannot follow
|
|
30
|
+
- Works fully offline with no cloud infrastructure
|
|
31
|
+
|
|
32
|
+
**Harder:**
|
|
33
|
+
- Requires a capable LLM backend for code generation
|
|
34
|
+
- Sandbox security must be maintained rigorously
|
|
35
|
+
- Latency is higher than vector similarity search for simple lookups (mitigated by KB cache)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Architecture Decision Records
|
|
2
|
+
|
|
3
|
+
This directory contains Architecture Decision Records (ADRs) for the factq project.
|
|
4
|
+
|
|
5
|
+
## Index
|
|
6
|
+
|
|
7
|
+
| ADR | Title | Status | Date |
|
|
8
|
+
|-----|-------|--------|------|
|
|
9
|
+
| [001](001-rlm-over-rag.md) | Use RLM over RAG for knowledge retrieval | Accepted | 2026-02-28 |
|
|
10
|
+
|
|
11
|
+
## Template
|
|
12
|
+
|
|
13
|
+
Use `TEMPLATE.md` when creating new ADRs. Number sequentially (e.g., `002-title.md`).
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# ADR-NNN: Title
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Proposed | Accepted | Deprecated | Superseded by [ADR-NNN](NNN-title.md)
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
What is the issue that we're seeing that is motivating this decision or change?
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
|
|
13
|
+
What is the change that we're proposing and/or doing?
|
|
14
|
+
|
|
15
|
+
## Consequences
|
|
16
|
+
|
|
17
|
+
What becomes easier or more difficult to do because of this change?
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "factq"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Your LLM's Local Source of Truth — a local-first knowledge base and verification engine for hallucination prevention."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = { text = "Apache-2.0" }
|
|
7
|
+
requires-python = ">=3.12"
|
|
8
|
+
authors = [{ name = "FactQ Team" }]
|
|
9
|
+
keywords = [
|
|
10
|
+
"llm",
|
|
11
|
+
"hallucination",
|
|
12
|
+
"verification",
|
|
13
|
+
"knowledge-base",
|
|
14
|
+
"rlm",
|
|
15
|
+
"mcp",
|
|
16
|
+
"factuality",
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 3 - Alpha",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"License :: OSI Approved :: Apache Software License",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
26
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
27
|
+
"Typing :: Typed",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
dependencies = [
|
|
31
|
+
"click>=8.1",
|
|
32
|
+
"rich>=13.0",
|
|
33
|
+
"pydantic>=2.0",
|
|
34
|
+
"pyyaml>=6.0",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
mcp = [
|
|
39
|
+
"mcp>=1.0",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://factq.dev"
|
|
44
|
+
Documentation = "https://factq.dev"
|
|
45
|
+
Repository = "https://github.com/factq-dev/factq-cli"
|
|
46
|
+
Issues = "https://github.com/factq-dev/factq-cli/issues"
|
|
47
|
+
Changelog = "https://github.com/factq-dev/factq-cli/blob/main/CHANGELOG.md"
|
|
48
|
+
|
|
49
|
+
[project.scripts]
|
|
50
|
+
factq = "factq.cli:main"
|
|
51
|
+
|
|
52
|
+
[build-system]
|
|
53
|
+
requires = ["hatchling"]
|
|
54
|
+
build-backend = "hatchling.build"
|
|
55
|
+
|
|
56
|
+
[tool.hatch.build.targets.wheel]
|
|
57
|
+
packages = ["src/factq"]
|
|
58
|
+
|
|
59
|
+
[tool.uv]
|
|
60
|
+
dev-dependencies = [
|
|
61
|
+
"pytest>=8.0",
|
|
62
|
+
"pytest-cov>=6.0",
|
|
63
|
+
"pytest-asyncio>=0.24",
|
|
64
|
+
"ruff>=0.9",
|
|
65
|
+
"mypy>=1.14",
|
|
66
|
+
"pre-commit>=4.0",
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
[tool.ruff]
|
|
70
|
+
target-version = "py312"
|
|
71
|
+
line-length = 100
|
|
72
|
+
src = ["src"]
|
|
73
|
+
|
|
74
|
+
[tool.ruff.lint]
|
|
75
|
+
select = ["E", "F", "I", "N", "UP", "B", "SIM", "TCH"]
|
|
76
|
+
|
|
77
|
+
[tool.mypy]
|
|
78
|
+
python_version = "3.12"
|
|
79
|
+
strict = true
|
|
80
|
+
warn_return_any = true
|
|
81
|
+
warn_unused_configs = true
|
|
82
|
+
|
|
83
|
+
[tool.pytest.ini_options]
|
|
84
|
+
testpaths = ["tests"]
|
|
85
|
+
addopts = "-ra -q"
|