bgleton1031/secure-ai-knowledge-assistant
GitHub: bgleton1031/secure-ai-knowledge-assistant
面向生产环境的安全优先本地 RAG 系统,通过组织隔离、角色控制、注入防御和审计日志解决受监管组织中 AI 可信访问内部知识的问题。
Stars: 0 | Forks: 0
🔐 安全 AI 知识助手 (SAKA)
一个面向生产环境、安全优先的 RAG 系统,专为需要真正掌控 AI 的组织而构建。
为什么开发这个系统
大多数希望引入 AI 的组织都面临同样的问题:现成的 AI 系统没有内部边界的概念。它们会产生幻觉,从任何地方寻找答案。它们缺乏访问控制,没有审计追踪,也无法解释它们做了什么或为什么这么做。 SAKA 的设计初衷就是为了解决这个问题——不是在策略层,而是在系统层。 这是一个本地部署、基于文档的 AI 助手,将安全控制作为核心架构,而不是事后附加。每一个设计决策——从检索范围到角色强制执行再到审计日志——都是在假设该系统将在受监管或高度关注安全的环境中运行的前提下做出的。
技术架构与设计决策
检索 — 语义向量搜索 (v2)
SAKA v2 用语义向量搜索取代了基于关键词的检索,该功能由本地 embedding 模型(通过 Ollama 使用 nomic-embed-text)和作为持久化向量存储的 ChromaDB 提供支持。在索引时,文档被切分为 300 字的重叠段落,进行一次 embedding,并持久化到磁盘——从而避免了每次重启时重新进行 embedding。
在查询时,用户的问题会被 embedding,并使用余弦相似度与已索引的 chunk 进行比较。系统会检索出语义相关性排名前 3 的段落,并将其作为上下文传递给 LLM。每个源文档都会显示相关性分数,以便用户准确了解为什么该文档被选中。
这种方法实现了语义上的灵活性(即使不存在确切的关键词也能找到相关内容),同时将所有数据保留在本地——没有外部 API 调用,数据也不会离开本机。
基于角色的访问控制 — 组织感知,向量存储强制执行
SAKA v2 中的 RBAC 在两个层面上得到执行:文档路由和向量存储隔离。 每个组织(MSP、律师事务所、医疗机构、SMB)都有自己专属的 Chroma collection。当用户查询系统时,他们只能查询其所属组织的 collection——即使是间接地,他们也无法访问属于其他组织的文档。访问控制决策发生在组装 LLM 上下文之前,而不是之后。 角色层级(basic → staff → technician → senior → admin)控制着组织内的权限。全局 admin 账号拥有跨所有 collection 的完全访问权限,并且是唯一可以查看审计日志或触发索引重建的账号。 这与企业数据架构中使用的深度防御模式相同——在存储层进行隔离,而不仅仅是在展示层。
Prompt Injection 缓解 — 基于模式的检测层
在输入到达检索或生成 pipeline 之前,一个预查询检查层会扫描已知的注入模式。被拦截的模式包括指令覆盖尝试、文档枚举请求和提权语言。这是一种基于黑名单的方法——对已知的攻击特征非常有效,但也承认其局限性,即应对新型的注入模式需要更新规则。 这与企业 WAF 配置中使用的深度防御模式相同——采用多重控制层,而不是单一的信任边界。
审计日志 — 结构化事件捕获
每次查询都会记录:时间戳、用户名、角色、输入、响应状态(ANSWERED / BLOCKED / NOT_FOUND / ERROR)以及源文档。日志 schema 专为下游 SIEM 摄取而设计——字段一致且可解析。这不是为了调试而记录日志;而是为了问责和事件重建而记录日志。
目标部署环境
SAKA 专为那些因数据治理要求而限制 AI 采用的环境而设计:在 NDA 下管理客户数据的 MSP、在 HIPAA 下运营的医疗机构、受 SOX 或 SEC 数据处理规则约束的金融服务公司,以及任何需要向审计师或合规官展示 AI 问责制的组织。 该系统被特意限定在内部知识管理的用例中——其价值在于对组织知识进行受控、有根据的 AI 访问,同时避免数据泄露、产生幻觉的策略或未经授权的文档访问的风险。
项目拆解
该项目演示了如何构建一个安全的 AI 系统,它能够:
- 仅从批准的内部文档中回答问题(无幻觉) - 将每个用户路由到其组织的隔离向量存储 - 在检索层执行基于角色的访问控制 - 在恶意和越权查询到达 LLM 之前将其拦截 - 使用结构化、可审计的记录记录所有活动 - 通过针对特定组织的文档集支持多个垂直领域🎯 问题
大多数 AI 系统:
❌ 瞎编答案(产生幻觉)❌ 跨角色泄露敏感数据
❌ 容易被 prompt injection 操纵
❌ 没有组织边界的概念
❌ 不提供审计追踪
✅ 解决方案
- 语义 RAG — 答案仅基于批准的文档 - 每个组织独立的 Chroma collection — 在向量存储层面实现组织隔离 - 基于角色的访问 — 在组装 LLM 上下文之前强制执行 - Prompt injection 拦截 — 查询前的模式检测层 - 完整的审计日志 — 记录每一次查询、每一个结果、每一个来源🧱 Architecture
流程:
1. 用户选择账号 → 确定组织和角色
2. 系统加载该组织专属的 Chroma collection
3. 用户提交问题 → 运行查询前注入检查
4. 对问题进行 embedding → 针对该组织的 collection 进行余弦相似度搜索
5. 检索出相关性得分最高的前 3 个 chunk
6. 将上下文 + 问题发送给本地 LLM (Ollama / llama3.2)
7. 模型仅使用该上下文生成答案
8. 显示答案、源文档和相关性得分
9. 将事件写入审计日志
🧠 核心功能
🔎 语义向量搜索
- 在索引时将文档切分为 300 字的重叠段落 - 通过 Ollama 在本地使用nomic-embed-text 进行 embedding
- 存储在持久的 ChromaDB collection 中(每个组织一个)
- 查询时进行余弦相似度检索
- 显示每个来源的相关性得分(颜色编码:绿/黄/红)
🏢 多垂直领域演示账号
SAKA 内置了跨越四个垂直领域的演示账号,每个账号都路由到各自的文档集和 Chroma collection:
| 组织 | 账号 | 角色 | |---|---|---| | Universal | admin1 | admin (完全访问权限,所有组织) | | MSP | tech1 | technician | | Law Office | reception1 / paralegal1 / attorney1 | basic / staff / senior | | Medical Office | frontdesk1 / ma1 / provider1 | basic / staff / senior | | SMB | employee1 / manager1 / it1 | basic / senior / technician |🚫 Prompt Injection Protection
拦截包含以下模式的查询:
- "admin credentials" / "domain admin" / "break-glass"
- "firewall admin" / "private key" / "vpn secret"
- "privileged access" / "administrator password"
👤 Role-Based Access Control
- 按组织隔离 Chroma collection — 用户只能查询其所属组织的文档
- 角色层级:basic → staff → technician → senior → admin
- admin 是全局的 — 是唯一有权访问受限文档和审计日志的账号
- 在组装 LLM 上下文之前强制执行访问控制
📋 Audit Logging
记录每一次查询:
- 时间戳
- 用户名 + 角色
- 问题
- 状态 (ANSWERED / BLOCKED / NOT_FOUND / ERROR)
- 使用的源文档
🖥️ 应用演示
🏠 Home Screen
✅ Valid Question (Answer Found)
🚫 Prompt Injection Blocked
🔐 Security Controls
- 回答仅限于批准的文档 — 无外部数据,无幻觉
- 按组织隔离向量存储 — 杜绝跨组织数据泄露
- 在检索前拦截 prompt injection
- 在 collection 层面执行基于角色的访问控制
- 使用结构化、可审计的记录记录所有活动
🧰 技术栈
- Python - Streamlit - Ollama — 本地 LLM 推理 (llama3.2) + embeddings (nomic-embed-text)
- ChromaDB — 持久化本地向量存储
- pdfplumber — PDF 文本提取
- Requests
- pandas
⚙️ 安装说明
1. `git clone https://github.com/bgleton1031/secure-ai-knowledge-assistant` 2. `cd secure-ai-knowledge-assistant` 3. `pip install -r requirements.txt` 4. 拉取 embedding 模型:`ollama pull nomic-embed-text` 5. 拉取 LLM — 根据您的硬件进行选择(参见下文的性能说明): - 仅 CPU 的机器:`ollama pull llama3.2:1b` - 启用 GPU 的机器:`ollama pull llama3.2` 6. `streamlit run app/main.py`⚡ 性能说明
SAKA 完全在本地运行 — 没有外部 API,数据不会离开本机。LLM 推理速度完全取决于主机硬件。
- 仅 CPU(无独立 GPU): 在app/main.py 中设置 OLLAMA_MODEL = "llama3.2:1b" 以获得更快的响应速度。对于有根据的 RAG 用例,1B 模型在 CPU 上的速度快 2–3 倍,且质量损失极小。
- 独立 GPU: 设置 OLLAMA_MODEL = "llama3.2" (3B) 或更大版本。Ollama 会自动利用 CUDA 来显著加快推理速度。
- 生产环境部署: SAKA 采用容器化部署(Docker / AWS ECS)架构,GPU 加速实例可以彻底消除本地硬件的限制。
本地 CPU 部署是专为演示和气隙环境设计的。相同的代码库无需修改即可部署到云基础设施中。