内容
<p align="center">
<img src="./faultline_logo.svg" alt="FaultLine" width="420"/>
</p>
<h1 align="center">FaultLine</h1>
<p align="center"><strong>为您的AI提供验证、私有、可共享的内存。</strong></p>
<p align="center">
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-AGPL%20v3-blue.svg" alt="License: AGPL v3"/></a>
<img src="https://img.shields.io/badge/python-3.11%2B-blue" alt="Python 3.11+"/>
<img src="https://img.shields.io/badge/OpenWebUI-0.6%2B%20(0.10.x%20tested)-green" alt="OpenWebUI"/>
<img src="https://img.shields.io/badge/MCP-2025--03--26-purple" alt="MCP"/>
</p>
---
FaultLine 为您的本地 AI 添加持久、验证的内存。事实存储在结构化的知识图谱中 - 而不是总结成文本块,也不是从文档中猜测。当您纠正某些内容时,它会更新。当您稍后询问时,答案是正确的。
---
## 为什么选择FaultLine
### 1. 私有设计
所有内容都在您的机器上运行。您的对话、记忆、数据 - 都不会离开。没有云同步,没有账户,没有订阅。
### 2. 跨任意AI共享内存
FaultLine 暴露了一个 MCP 服务器。这意味着相同的内存存储可供 OpenWebUI、Claude Desktop 或其他任何支持 MCP 的端点使用。在一个对话中更改服务器 IP,其他模型会看到更新。
### 3. 编写验证的事实 - 而不是 RAG 猜测
RAG 检索文档并要求 LLM 解释它们。答案取决于措辞、上下文和运气。FaultLine 在存储之前验证事实,并拒绝虚构的细节。您的 AI 知道“AlphaNode 的 IP 是 10.44.5.20” - 而不是“文档中提到了有关服务器的内容”。
### 4. 可纠正的关系数据
事实存储为类型化的关系 - 人、年龄、职业、网络设备、IP地址、MAC、主机名。更正会干净地更新记录;旧值会被存档,而不是丢失。记忆随着时间的推移而加强:曾经提到的事情会被轻微地记住,确认的事实会变得有权威。
### 5. 按需教它任何领域
`/expand networking` 教 FaultLine 网络是如何工作的,然后您再提及您的第一个设备。`/expand kubernetes online https://kubernetes.io/docs/concepts/` 读取实际的文档并从中构建本体结构。你指向源,它学习结构,你在该领域提到的每个事实都存储并在上下文中检索 - 而不是作为一个孤立的字符串。并且它学习的一切仍然可以被你纠正。
---
## 实践中的表现
```
您: "我是一名系统管理员。我的主要工作站叫做 DevBox,IP 地址是 10.0.1.5。"
下一次会话:
您: "您对 DevBox 有什么了解?"
AI: "DevBox 是您的工作站,IP地址 10.0.1.5。"
```
```
您: "实际上 DevBox 移动到了 10.0.1.10 进行了网络更改。"
下一次会话:
您: "DevBox 的 IP 地址是多少?"
AI: "DevBox 的 IP 地址是 10.0.1.10。"
```
```
您: /expand networking
稍后,在提及您的防火墙后:
AI: "您的防火墙 OPNsense 是一种网络设备 - 我从之前就知道这一点。"
```
**人员、偏好、服务器 IP 地址、MAC 地址、主机名、关系、更正。** 您告诉它的任何内容,都存储并准备就绪。
---
## 它是如何工作的(简要介绍)
- 每个消息都会被扫描以查找值得保留的事实
- 事实在存储之前会经过验证关口 - 虚构的细节会被拒绝
- 相关事实会在 AI 响应之前被注入对话
- 记忆会随着确认而加强;更正会干净地存档旧值
- `/expand <topic>` 教 FaultLine 一个领域的结构,以便关于它的事实能够正确落地
---
## `/expand` - 按需领域智能
大多数内存系统存储事实。FaultLine 可以学习一个**领域**的结构、关系和词汇,以便关于它的事实能够正确落地并且有意义。
没有领域扩展,“我的防火墙是 OPNsense” 存储为一个扁平字符串。有了 `/expand networking`,FaultLine 知道防火墙是一种网络设备,它有 IP 地址,它位于您的 LAN 和 WAN 之间,以及它与交换机、路由器和主机之间的关系。您提及的每个网络事实都会存储和检索在上下文中。
**实践中的差异:**
```
没有 /expand:
您: "OPNsense 在 10.0.0.1,交换机在 10.0.0.2"
AI: "OPNsense 有 IP 10.0.0.1 并且交换机有 IP 10.0.0.2。"
(两个孤立的事实,没有关系,没有结构)
启用 networking 扩展:
您: "OPNsense 在 10.0.0.1,交换机在 10.0.0.2"
AI: "您的防火墙 OPNsense 在 10.0.0.1。您的交换机在 10.0.0.2,
在它下面。"(以关系存储 - 设备类型、角色、拓扑)
```
### 您控制源
指向实际的文档,它会将扩展内容固定在这些材料上 - 而不是 LLM 猜测该领域是什么样的:
```
/expand kubernetes online https://kubernetes.io/docs/concepts/
/expand tls online https://www.rfc-editor.org/rfc/rfc8446
/expand networking
/expand home lab
/expand kubernetes
```
如果没有 URL,它会根据其训练知识进行推理。如果有,它会读取源并从中构建本体结构。您可以决定需要多大的权威。
### 仍然可纠正
`/expand` 构建的所有内容都受与任何其他事实相同的更正规则约束。如果它将领域结构搞错了,请告诉它 - 您的更正获胜并存储为权威。扩展是一个起点,而不是约束。
### 它会复合
一次性扩展,然后每个领域的后续对话都会自动受益。新的事实会进入正确的关系中。对该领域的查询会返回结构化、上下文的答案,而不是孤立的字符串。使用得越多,越有用。
---
## 比较
| | FaultLine | ChatGPT Memory | MemGPT / Letta | Mem0 | OpenWebUI RAG |
|---|---|---|---|---|---|
| 自主部署、完全私有 | ✅ | ❌ 仅限云端 | ✅ | ✅ | ✅ |
| 与任何本地 LLM 合作 | ✅ | ❌ 仅限 OpenAI | ✅ | ✅ | ✅ |
| MCP 服务器 - 跨模型共享 | ✅ | ❌ | ❌ | 部分 | ❌ |
| 编写验证(无幻觉存储) | ✅ | ❌ | ❌ | ❌ | ❌ |
| 可纠正 - 清洁更新,存档旧值 | ✅ | ❌ 覆盖 | ❌ | ❌ | ❌ |
| 关系事实(不是文档块) | ✅ | ❌ | 部分 | 部分 | ❌ |
| 记住服务器 IP 地址、MAC 地址、主机名 | ✅ | ❌ | ❌ | ❌ | ❌ |
| 记住关系和人员 | ✅ | ✅ | 部分 | 部分 | ❌ |
| 短期 → 长期提升 | ✅ | ❌ | 部分 | ❌ | ❌ |
| `/expand` 主题学习 | ✅ | ❌ | ❌ | ❌ | ❌ |
| 基于 Web 的学习 | ✅ | ❌ | ❌ | ❌ | ❌ |
| 死亡命名/首选名称支持 | ✅ | ❌ | ❌ | ❌ | ❌ |
| 每用户私有内存 | ✅ | ✅ 账户 | ✅ | ✅ | ❌ 共享 |
| 开源 | ✅ AGPLv3 | ❌ | ✅ MIT | 部分 | ✅ MIT |
---
## 多租户隔离
每个用户都有一个**物理独立的 PostgreSQL 模式** (`faultline_<user_id>`) 和自己的 Qdrant 集合。每个请求都绑定到调用者的模式,使用 `SET search_path` **不带 `public`**,因此一个租户的查询甚至无法**命名**另一个租户的表。没有共享的 `user_id` 列需要过滤 - 边界是数据库强制的。
**在实时实例上验证。** 三个全新的租户,每个租户都讲述一个不同的故事,然后检查:
| 租户 | 讲述 | 存储在其模式中 | 其他租户的数据? |
|---|---|---|---|
| A | 一只名叫 Mittens 的猫 | `cat → feline → mammal → animal` | **无** |
| B | 一辆红色特斯拉 Model 3 | `tesla → vehicle → transportation_device` | **无** |
| C | 住在柏林,德国 | `berlin → city`, `germany → country` | **无** |
每个模式都只包含**自己的实体和层次结构** - 零跨租户令牌。以一个租户的身份发出召回请求,只能从该租户的模式中读取,因此在结构上不可能将一个用户的内存显示给另一个用户。(每个租户的 `±6` 层次结构也独立增长 - 不仅在休息时。)
---
## 要求
- Docker 和 Docker Compose
- LLM 后端 - [Ollama](https://ollama.ai/)、 [LM Studio](https://lmstudio.ai/)、 [OpenWebUI](https://openwebui.com/) 或托管 API(OpenAI、Anthropic、Groq)
- 至少 8 GB 内存,建议 16 GB
---
## 入门指南
```bash
git clone https://github.com/tkalevra/FaultLine.git
cd FaultLine
```
**引导式设置(推荐)。** 交互式向导首先询问 **语言 / Lingua**,然后选择您的 LLM 后端,**测试连接并列出可用的模型供您选择**,生成一个秘密的 `MCP_API_KEY`,设置您的租户 ID,并编写一个可以直接使用的 `.env` - 然后打印您需要粘贴到客户端的确切内容:
```bash
./setup.sh # Linux / macOS
setup.bat # Windows
# 或,在任何平台上: python3 quickstart.py
```
> **🌍 语言。** 向导以语言选择开始。**English** 继续在 `main` 上。**Italiano** (实验性)切换到 `it` 分支 - 非官方、正在进行的意大利实例(意大利设置 + `LEGGIMI-it.md`);提取功能通过 LLM 路径进行。尚未生产就绪 - 自行承担风险;对于稳定版本,请留在 English/`main` 上。
**或手动配置:
```bash
cp .env.example .env
# 设置 LLM_BACKEND_TYPE + LLM_BASE_URL 以指向您已经运行的 LLM
# (Ollama、LM Studio、OpenWebUI、OpenAI、Anthropic、...)
docker compose up -d
curl http://localhost:8000/health
# {"status": "ok", ...}
```
重新运行连接检查,随时使用 `python3 quickstart.py --validate`。
FaultLine 连接到您已经运行的 LLM - 它不托管一个。(如果您*没有*现成的模型,`docker compose --profile ollama up -d` 启动一个捆绑的 Ollama 与堆栈一起。)
第一次启动下载 GLiNER2 提取模型(~500 MB,仅限 CPU - 无需 GPU 或 CUDA )。需要 3-5 分钟。
### 连接客户端
两个独立的选择 - 向导处理两者,或者手动设置它们。
**1. FaultLine 对话的 LLM(`LLM_BACKEND_TYPE` + `LLM_BASE_URL` - 主机+端口,仅限主机名):
| 后端 | `LLM_BACKEND_TYPE` | `LLM_BASE_URL`(示例)|
|---|---|---|
| LM Studio | `lm_studio` | `http://host.docker.internal:1234` |
| Ollama | `ollama` | `http://host.docker.internal:11434` |
| OpenWebUI | `openwebui` | `http://open-webui:8080` |
| OpenAI / Anthropic / Groq | `openai` / `anthropic` / `groq` | 提供商 API 基本 URL |
**2. 您的聊天客户端如何调用 FaultLine 的内存工具 - 通过 **MCP 服务器上的 `:8002`**(Bearer `MCP_API_KEY`)。任意数量的客户端可以同时共享一个存储:
- **OpenWebUI** → 设置 → 工具 → `+`(OpenAPI),或管理员设置 → 外部工具(原生 MCP) *(以下)*
- **Claude Desktop** → `.mcpb` 扩展 *(以下)*
- **Cursor / 其他 MCP 客户端** → `http://<host>:8002/mcp` 并带有 `Authorization: Bearer <MCP_API_KEY>`
### 连接到 OpenWebUI
*针对 OpenWebUI v0.10.x(最新版本)进行验证。以下路径从 v0.6.31+ 适用)*
* **Cursor / 其他 MCP 客户端** → `http://<host>:8002/mcp` 带有 `Authorization: Bearer <MCP_API_KEY>`
### 连接到 OpenWebUI
*已针对 OpenWebUI v0.10.x(最新)进行验证。以下路径适用于 v0.6.31+。OpenWebUI 的菜单标签在版本之间会发生变化 - 查找 **Tools**(OpenAPI)或 **External Tools**(原生 MCP)如果您的版本不同。*
FaultLine 的服务器在 `:8002` 上支持 **OpenAPI 和原生 MCP**,因此 OpenWebUI 可以通过两种方式访问它。**使用选项 A** - 这是唯一一个可靠地转发每个用户身份标头的路径。
**选项 A - OpenAPI 工具服务器(推荐):**
1. **设置 → 工具 → `+`** (管理工具服务器)。对于实例范围的服务器,请改用 **管理员设置 → 工具**。
2. **网址:** `http://faultline-mcp:8002` (在同一 Docker 网络中)或 `http://<host>:8002`。模态窗口可能会预填充 `https://` - 将其更改为 `http://` 以获取本地服务器,然后点击 **刷新** 进行测试。
3. **身份验证:** `Bearer` → 您的 `MCP_API_KEY`。
4. 设置 `ENABLE_FORWARD_USER_INFO_HEADERS=true` 在 OpenWebUI 的环境中,以便每个用户的内存都被作用于他们。它会转发 `X-OpenWebUI-User-Id` 头(也适用于 `-User-Name`/`-Email`/`-Role`)- 没有它,基于用户的内存将不起作用。
OpenWebUI 读取 `/openapi.json` 并在每个对话中显示 `recall_memory`、`remember_facts`、`retract_fact` 作为工具。
**选项 B - 原生 MCP(OpenWebUI 0.6.31+):**
1. **管理员设置 → 外部工具 → `+`** (添加服务器)- 原生 MCP **仅限管理员**。
2. **类型:** `MCP (Streamable HTTP)`(OpenWebUI 支持的唯一传输类型)。
3. **网址:** `http://<host>:8002/mcp` · **身份验证:** `Bearer` → 您的 `MCP_API_KEY`。
> ⚠️ **原生 MCP 是较新的、测试较少的路径与 FaultLine 配合使用**(其 `/mcp` 是一个无状态的 JSON-RPC 端点)- 如果服务器或工具不显示,请使用 **选项 A**。并且基于用户的范围较弱:截至 v0.10.x,`ENABLE_FORWARD_USER_INFO_HEADERS` **不** 通过原生 MCP 转发 `X-OpenWebUI-User-*` 头,并且自定义标头模板令牌(`{{USER_ID}}`)可能无法在那里解析 [*open-webui#21134](https://github.com/open-webui/open-webui/issues/21134)。对于可靠的基于用户的内存,请使用 **选项 A**;如果您运行原生 MCP,请固定一个租户并使用 `FAULTLINE_USER_ID`。
**工具触发(弱模型)。**截至 v0.10.0,OpenWebUI 默认每个模型都设置为 **原生** 函数调用(旧的“默认”模式已重命名为 **“旧版”** 并且不受支持)。原生适用于大多数 2024+ 模型;如果较小的模型(Qwen、Llama、Mistral、Phi)无法可靠地调用工具,请切换 **聊天控件 → 高级参数 → 函数调用 → 旧版**(或在模型/全局下设置每个模型)。
> **旧版替代方案:** 插座/出口过滤器(`openwebui/faultline_function.py`,工作区 → 函数)仍然存在用于自动注入,但上述工具服务器路径是支持的路径。
---
## Claude Desktop(MCP)
FaultLine 随附一个 `.mcpb` 扩展程序,用于在 Claude Desktop 中进行一次性安装。
### 安装扩展
1. 构建扩展(需要 Python):
```bash
cd tools/claude-desktop
python build_mcpb.py
# → 产生 faultline.mcpb
```
2. 在 Claude Desktop 中:**设置 → 扩展 → 高级设置 → 安装扩展** → 选择 `faultline.mcpb`
3. Claude Desktop 提示输入三个值:
| 字段 | 它是什么 | 如何获取 |
|---|---|---|
| **FaultLine MCP URL** | MCP 服务器的 HTTP 端点 | 默认值:`http://localhost:8002`。如果 FaultLine 在另一台机器上运行,请更改主机。 |
| **用户 ID** | 隔离内存存储的 UUID | 生成一个:`python -c "import uuid; print(uuid.uuid4())"`。如果您还使用 OpenWebUI,请从 **OpenWebUI → 设置 → 账户** 使用相同的 UUID,以便两个客户端共享一个内存存储。 |
| **MCP API 密钥** | 身份验证的 Bearer 令牌 | 必须与您的 `.env` 中的 `MCP_API_KEY` 匹配。生成一个:`python -c "import secrets; print(secrets.token_hex(32))"` |
4. 确保您的 Docker 堆栈正在运行(`docker compose up -d`)- 扩展程序连接到端口 8002 上的 MCP 服务器。
### 工作原理
该扩展是一个薄的 stdio 到 HTTP 代理。Claude Desktop 将其作为本地进程启动;它将 JSON-RPC 消息转发到您的 Docker MCP 服务器。无需 SDK 依赖 - 仅使用 Python 标准库。
```
Claude Desktop(stdio)→ faultline_proxy.py → HTTP → localhost:8002/mcp → Docker
```
### 替代方案:直接 HTTP(流式 HTTP 客户端)
支持直接 HTTP 传输的 MCP 客户端(无需 stdio)可以直接连接,无需扩展:
```json
{
"mcpServers": {
"faultline": {
"url": "http://YOUR-HOST:8002/mcp",
"headers": { "Authorization": "Bearer YOUR_MCP_API_KEY" }
}
}
}
```
### 可用工具
| 工具 | 描述 |
|---|---|
| `recall_memory` | 查询知识图谱 - 检索与对话相关的事实 |
| `remember_facts` | 从对话文本中提取和存储事实 |
| `learn_facts` | 直接导入结构化事实三元组 |
| `retract_fact` | 从知识图谱中删除一个事实 |
所有四个工具都使用与您的 OpenWebUI 会话写入的同一个存储。
### 系统提示(重要)
FaultLine 在模型明确指示使用 MCP 工具进行所有内存操作时效果最佳。没有系统提示时,一些客户端(尤其是 Claude Desktop)将使用其内置内存而不是 FaultLine。
准备粘贴的提示位于 [`prompts/`](prompts/) 文件夹中:
| 文件 | 使用时机 |
|---|---|
| [`strong-model-prompt.md`](prompts/strong-model-prompt.md) | Claude、GPT-4o、Gemini Pro - 带有可靠工具调用的模型 |
| [`weak-model-prompt.md`](prompts/weak-model-prompt.md) | Qwen、Llama、Mistral、Phi - 需要显式、分步指令的较小模型 |
选择与您的模型匹配的文件,将提示块复制并粘贴到客户端的系统提示字段中。
---
## 环境变量
```env
# LLM 钩子 - FaultLine 与之交互的模型服务器。
# LLM_BACKEND_TYPE 选择协议;自动附加 API 路径。
LLM_BACKEND_TYPE=ollama # openwebui | ollama | lm_studio | openai | anthropic | groq | localai | raw
LLM_BASE_URL=http://host.docker.internal:11434 # 主机 + 端口,仅限
LLM_API_KEY= # 空值适用于本地服务器;令牌适用于托管 API
# 存储
POSTGRES_DSN=postgresql://faultline:faultline@postgres:5432/faultline
QDRANT_URL=http://qdrant:6333
# MCP 服务器
MCP_API_KEY= # 留空表示无身份验证,或设置一个秘密令牌
FAULTLINE_USER_ID= # 可选 - 将 MCP 服务器固定到一个用户
```
查看 [`.env.example`](.env.example) 以获取完整的列表和描述。
---
## 关键文件
| 文件 | 它是什么 |
|---|---|
| `quickstart.py` · `setup.sh` · `setup.bat` | 引导式设置向导 - 编写 `.env`,测试连接,列出您的模型 |
| `src/mcp/server.py` | MCP 工具服务器 - 实时集成路径 |
| `src/api/main.py` | 后端 API |
| `openwebui/faultline_function.py` | 旧版 OpenWebUI 过滤器(首选 MCP 工具服务器) |
| `migrations/` | 数据库模式 - 在第一次启动时自动运行 |
---
## 使用的技术
[PostgreSQL](https://www.postgresql.org/) · [Qdrant](https://qdrant.tech/) · [Redis](https://redis.io/) · [FastAPI](https://fastapi.tiangolo.com/) · [GLiNER2](https://github.com/fastino-ai/GLiNER2) · [nomic-embed-text-v1.5](https://huggingface.co/nomic-ai/nomic-embed-text-v1.5) · [OpenWebUI](https://openwebui.com/)
---
## 许可
FaultLine 是 **开源** 的,基于 **[GNU AGPLv3](./LICENSE)** 许可。
**如果您是用户,这不会改变任何内容。** 运行它,修改它,自我托管它 - 为自己或您的公司 - 永远免费。那就是它的用途。
AGPL 只要求一件事:**如果您修改 FaultLine 并通过网络向他人提供您的修改版本,您的用户将获得您的修改后的源代码。** 改进措施进入公共领域。不要修改它,您只需遵守许可通知。
如果这不适合您 - 您想构建一个封闭源代码的产品,或将 FaultLine 嵌入专有产品中 - **提供商业许可**。打开一个问题或联系。
> **许可历史:** FaultLine 在 `433daf1` 提交之前为 Apache-2.0。通过该提交获得的副本仍然为 Apache-2.0。 从该提交之后的所有内容均为 AGPLv3。参见 [NOTICE](./NOTICE)。
## 贡献
欢迎贡献,并且有一个**签署的 CLA(贡献者许可协议)**。它的存在是为了让项目能够保持双重许可,这是开源引擎资金支持的原因 - 理由在 **[CONTRIBUTING.md](./CONTRIBUTING.md)** 中诚实地阐述。你保留你在作品中的版权。
房屋规则,简而言之:
- 新的关系类型属于 `rel_types` 数据库表,而不是代码
- GLiNER2 零镜头标签从不修改为承载提取模式或描述
- 用户看到的任何内容中没有 UUID
- 强数据导入,精简查询 - 如果召回错误,在导入时修复
- 所有测试通过:`pytest tests/`
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器