1. 项目概述:Ollama+SimpleRAG本地RAG实践
最近在尝试将大模型能力整合到本地应用中时,发现SimpleRAG这个基于WPF和Semantic Kernel的开源项目特别适合作为入门案例。它完整实现了RAG(检索增强生成)的核心流程,而且支持通过Ollama调用本地大模型,完美解决了网络环境受限时的开发需求。这个方案特别适合以下场景:
- 需要保护数据隐私的企业内部知识库系统
- 网络条件不稳定但需保证服务可用的环境
- 想低成本体验RAG完整流程的开发者
我在Windows 11 + RTX 3060环境下实测,使用Ollama部署7B参数的本地模型,配合SimpleRAG能流畅实现文档问答功能。整个过程不需要任何云服务API密钥,所有数据处理都在本地完成。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与工具链配置
2.1 Ollama的离线部署技巧
官方推荐的安装方式是通过命令行curl -fsSL https://ollama.com/install.sh | sh下载,但在国内网络环境下经常遇到下载中断。这里分享两种可靠方案:
方案A:使用国内镜像源
bash复制# 使用中科大镜像加速
curl -fsSL https://mirrors.ustc.edu.cn/ollama/install.sh | sh
方案B:手动安装包部署
- 从GitHub releases页面下载最新
.msi安装包 - 以管理员身份运行安装程序时,在目标路径选择界面修改为D盘等非系统盘
- 安装完成后需要手动添加环境变量:
powershell复制[Environment]::SetEnvironmentVariable(
"Path",
[Environment]::GetEnvironmentVariable("Path", [EnvironmentVariableTarget]::User) + ";D:\Ollama\bin",
[EnvironmentVariableTarget]::User)
注意:安装完成后建议立即执行
ollama pull llama2:7b-chat开始拉取模型,这个步骤耗时较长(约4小时/100Mbps带宽),可以安排在夜间进行。
2.2 SimpleRAG项目准备
从GitHub克隆项目后,需要特别注意.NET 8 SDK的版本匹配问题:
bash复制git clone https://github.com/Ming-jiayou/SimpleRAG.git
cd SimpleRAG
推荐使用VS2022打开项目时,先检查解决方案资源管理器中的目标框架:
- 右键项目 → 属性 → 应用程序 → 目标框架
- 确保显示".NET 8.0 (长期支持)"
- 如果缺少对应运行时,到.NET官网下载SDK
3. 核心配置详解
3.1 appsettings.json关键参数
配置文件需要从appsettings.example.json复制创建,以下是离线模式的核心配置项:
json复制{
"ChatAI": {
"ModelId": "llama2:7b-chat",
"Endpoint": "http://localhost:11434",
"ApiKey": "ollama" // 固定值即可
},
"Embedding": {
"ModelId": "llama2:7b",
"Endpoint": "http://localhost:11434",
"ApiKey": "ollama"
},
"TextChunker": {
"MaxChunkSize": 512
}
}
参数解析:
ModelId:对应Ollama已下载的模型名称,可通过ollama list查看Endpoint:Ollama默认服务地址(端口11434)MaxChunkSize:文档分块的最大token数,建议设置在256-1024之间
3.2 模型选择建议
对于消费级显卡(如RTX 3060 12GB),推荐以下Ollama模型组合:
| 任务类型 | 推荐模型 | 显存占用 | 性能表现 |
|---|---|---|---|
| 对话 | llama2:7b-chat | 6GB | 8 tokens/s |
| 嵌入 | llama2:7b | 5GB | 32 docs/s |
如果显存不足(如4GB显卡),可以考虑量化版本:
bash复制ollama pull llama2:7b-chat-q4_0 # 4bit量化版
4. 完整工作流程实现
4.1 文档处理流水线
SimpleRAG的文档处理流程分为三个阶段:
- 文本分块:按配置的chunk_size分割文档
- 向量化:通过Ollama生成文本嵌入
- 存储:将向量存入SQLite数据库
实测一个10MB的PDF文件处理耗时约3分钟(RTX 3060),主要瓶颈在模型推理环节。可以通过以下方式优化:
csharp复制// 在TextChunkerOptions中调整参数
services.Configure<TextChunkerOptions>(options => {
options.MaxChunkSize = 768; // 增大分块减少请求次数
options.OverlapSize = 128; // 添加重叠避免信息割裂
});
4.2 RAG问答实现原理
当用户提问时,系统会:
- 将问题转换为向量
- 在数据库中搜索相似文本块(余弦相似度)
- 将top3结果作为上下文注入prompt
- 调用对话模型生成最终回答
核心prompt模板如下:
code复制请基于以下上下文回答问题:
{{context}}
问题:{{question}}
回答时请:
- 严格基于给定上下文
- 如上下文无相关信息,回答"未找到相关依据"
- 使用中文回答
5. 常见问题排查指南
5.1 模型加载失败
现象:启动时报"Model not found"
- 确认Ollama服务已运行:
ollama serve - 检查模型是否下载:
ollama list - 验证模型名称拼写(区分大小写)
5.2 显存不足处理
解决方案:
- 降低并行请求数:在
Startup.cs中配置
csharp复制services.AddSemanticKernel(provider => {
provider.ConfigBuilder.MaxConcurrentCalls = 2;
});
- 使用
--numa参数启动Ollama:
bash复制ollama serve --numa # 启用NUMA优化
5.3 中文处理异常
如果模型对中文支持不好,可以:
- 在prompt中明确要求中文输出
- 使用
qwen:7b等中文优化模型 - 在文本分块时确保不切断中文字符:
csharp复制options.SplitOptions = new TextSplitOptions {
KeepSeparator = true,
LengthFunc = text => Encoding.UTF8.GetByteCount(text) / 3 // 中文字符计数修正
};
6. 性能优化实战技巧
6.1 缓存机制实现
在Services/EmbeddingService.cs中添加内存缓存:
csharp复制public class CachedEmbeddingService : IEmbeddingService
{
private readonly MemoryCache _cache = new(new MemoryCacheOptions());
public async Task<float[]> GetEmbeddingAsync(string text)
{
if(_cache.TryGetValue(text, out float[] cached))
return cached;
var embedding = await _innerService.GetEmbeddingAsync(text);
_cache.Set(text, embedding, TimeSpan.FromHours(1));
return embedding;
}
}
6.2 混合检索策略
修改Services/RetrievalService.cs实现关键词+向量混合搜索:
csharp复制var keywordResults = _fullTextSearch(query);
var vectorResults = await _vectorSearch(query);
// 加权融合算法
var combined = keywordResults
.Concat(vectorResults)
.GroupBy(x => x.Text)
.Select(g => new {
Text = g.Key,
Score = g.Sum(x => x.Score * (x.IsKeyword ? 0.3 : 0.7))
})
.OrderByDescending(x => x.Score);
7. 项目扩展方向
7.1 接入本地知识库
通过修改DocumentController.cs实现自动监控文件夹:
csharp复制var watcher = new FileSystemWatcher("KnowledgeBase");
watcher.Created += async (_, e) => {
await _documentService.ProcessDocumentAsync(e.FullPath);
};
watcher.EnableRaisingEvents = true;
7.2 支持更多文件格式
安装Gemini.NLExtensions包后扩展支持:
csharp复制services.AddDocumentProcessor<PdfDocumentProcessor>();
services.AddDocumentProcessor<WordDocumentProcessor>();
services.AddDocumentProcessor<ExcelDocumentProcessor>();
经过两周的深度使用,这套方案最让我惊喜的是在完全离线的环境下仍能保持可用性。虽然7B模型的生成质量不如GPT-4,但对于企业内部知识检索这类场景已经足够。一个实用建议:在处理大量文档前,先用小样本测试分块效果,避免因参数不当导致信息碎片化。
