AI生产数据分析WinForms项目笔记

一、项目概述

1. 核心目标

开发基于Windows窗体(WinForms)的本地AI数据分析工具,支持读取MongoDB/CSV格式的生产数据,调用本地部署的Ollama模型完成数据分析任务。核心满足三大要求:本地运行、非计算密集型(响应时间短)、具备精准的生产数据分析能力。

2. 技术栈

  • 前端:WinForms(基于.NET Framework 4.8,适配Windows桌面环境)

  • 数据层:MongoDB(通过MongoDB.Driver操作)、CSV(通过CsvHelper解析)

  • AI层:Ollama(本地部署,通过API调用模型进行分析)

  • 辅助工具:Newtonsoft.Json(数据JSON序列化/反序列化)、HttpClient(发送HTTP请求调用Ollama API)

二、环境准备

1. 开发环境

  • 开发工具:Visual Studio 2022(需提前安装.NET桌面开发组件)

  • 运行环境:Windows 10/11(64位系统,内存≥8GB,推荐16GB,保障模型运行流畅)

2. 必装NuGet包

包名 用途 安装方式(控制台)
MongoDB.Driver 操作MongoDB数据库(连接、查询、读取数据) Install-Package MongoDB.Driver
CsvHelper 解析CSV文件,读取文件中的生产数据 Install-Package CsvHelper
Newtonsoft.Json 实现数据的JSON序列化与反序列化,适配数据拼接和解析 Install-Package Newtonsoft.Json
System.Text.Json 解析Ollama API返回的JSON响应数据 (.NET Framework 4.8自带,无需额外安装,按需引用即可)

3. Ollama部署(本地AI环境)

  1. 下载安装:访问Ollama官网,下载Windows版本安装包,按默认步骤安装即可。安装完成后,Ollama会自动注册为Windows后台服务,支持开机自启。

  2. 服务验证:打开浏览器,访问http://localhost:11434,若页面显示「Ollama is running」,说明服务启动成功(该地址为项目调用Ollama API的核心地址)。

  3. 拉取轻量模型(推荐):

    • 优先选择phi3:mini模型(体积1.4GB,响应速度快,适配生产数据分析场景),终端执行命令:ollama pull phi3:mini

    • 模型验证:执行ollama list可查看已下载的模型;执行ollama run phi3:mini可手动测试模型响应,确保模型能正常生成回答。

三、WinForms界面搭建

1. 核心控件(Name属性+作用)

控件类型 Name 核心作用 关键属性配置
TextBox(多行) txtQuestion 供用户输入需要分析的问题 Multiline=True、ScrollBars=Vertical
ComboBox cmbDataSource 让用户选择数据来源(MongoDB或CSV文件) Items添加「MongoDB」「CSV文件」两个选项
Button btnSelectCsv 点击打开文件选择框,选择CSV文件并获取路径 Visible=False(默认隐藏,选择CSV数据源时显示)
TextBox txtCsvPath 显示选中的CSV文件路径 ReadOnly=True、Visible=False(与btnSelectCsv同步显示/隐藏)
Button btnSubmit 提交用户问题,触发数据读取、AI调用及结果展示流程 BackColor=LightBlue(提升视觉辨识度)
TextBox(多行) txtAnswer 显示Ollama模型返回的数据分析结果 Multiline=True、ReadOnly=True(禁止编辑结果)
Label lblStatus 显示当前处理状态(就绪、处理中、分析完成、分析失败) 默认Text=就绪
TextBox txbDatabase 供用户输入MongoDB数据库名称 默认值=ProductionDB(减少用户输入成本)
TextBox txbCollection 供用户输入MongoDB集合名称 默认值=ProcessData(减少用户输入成本)

2. 核心事件绑定

控件 事件 逻辑
cmbDataSource SelectedIndexChanged 切换数据源时,同步显示/隐藏btnSelectCsv和txtCsvPath控件
btnSelectCsv Click 打开文件选择对话框,用户选择CSV文件后,将路径赋值给txtCsvPath
btnSubmit Click(async void) 异步执行:读取数据源数据→构造Prompt→调用Ollama API→显示分析结果/错误信息

四、核心代码逻辑

1. 数据源读取(MongoDB/CSV)

  • 动态配置数据源:移除数据库名、集合名的硬编码,从txbDatabase、txbCollection控件中动态读取,并添加空值校验,避免因输入为空导致报错。

  • 灵活筛选数据:默认使用Builders<BsonDocument>.Filter.Empty查询所有数据,可扩展日期筛选功能(详见优化方向)。

  • 简化数据处理:移除ProcessData实体类,直接读取MongoDB的BsonDocument和CSV的dynamic动态类型,拼接为JSON格式文本,便于Ollama模型解析。

关键代码片段(MongoDB)

private async Task<string> GetDataAsync(string dataSource, string csvPath)
{
    if (dataSource == "MongoDB")
    {
        string mongoDatabaseName = txbDatabase.Text.Trim();
        string mongoCollectionName = txbCollection.Text.Trim();
        // 空值校验,避免无效输入
        if (string.IsNullOrEmpty(mongoDatabaseName)) throw new Exception("请输入MongoDB数据库名!");
        if (string.IsNullOrEmpty(mongoCollectionName)) throw new Exception("请输入MongoDB集合名!");
        
        var client = new MongoClient(_mongoConnectionString);
        var database = client.GetDatabase(mongoDatabaseName);
        var collection = database.GetCollection<BsonDocument>(mongoCollectionName);
        
        var filter = Builders<BsonDocument>.Filter.Empty;
        var dataList = await collection.Find(filter).Skip(0).Limit(50).ToListAsync(); // 分页控制数据量,避免Prompt过长
        StringBuilder sb = new StringBuilder();
        foreach (var doc in dataList)
        {
            sb.AppendLine(doc.ToJson(new JsonWriterSettings { Indent = true }));
            sb.AppendLine("---"); // 分隔不同数据文档,提升可读性
        }
        return sb.ToString();
    }
    // CSV读取逻辑(略,动态类型+JSON序列化,与MongoDB逻辑保持一致)
}

优化方向:新增日期筛选功能

核心思路:在现有界面新增控件,允许用户自主选择是否启用日期筛选、选择筛选日期,兼顾“查询全部数据”和“筛选指定日期数据”两种场景,适配生产数据按日期分析的实际需求,且不破坏原有功能逻辑。

具体实现方法
  1. 界面控件新增:在WinForms设计视图中,新增两个核心控件,无需复杂配置,满足基础筛选需求即可:

    • DateTimePicker控件:用于让用户选择需要筛选的具体日期,为日期筛选提供核心输入支持;

    • CheckBox控件:用于控制是否启用日期筛选功能,勾选则按指定日期筛选,未勾选则查询所有数据。

  2. 代码逻辑修改(核心片段):重点修改GetDataAsync方法,新增日期筛选参数,实现筛选逻辑:


// 1. 新增日期筛选参数filterDate,修改方法签名(核心修改)
private async Task<string> GetDataAsync(string dataSource, string csvPath, DateTime? filterDate)
{
    if (dataSource == "MongoDB")
    {
        // ...原有数据库名、集合名读取及校验逻辑不变(略)       
        // 2. 核心日期筛选逻辑(新增)
        FilterDefinition<BsonDocument> filter;
        if (filterDate.HasValue)
        {
            // 筛选指定日期数据(忽略时间部分,仅匹配日期)
            filter = Builders<BsonDocument>.Filter.Eq(x => x["Timestamp"].ToLocalTime().Date, filterDate.Value.Date);
        }
        else
        {
            // 未启用筛选,查询所有数据(保持原有逻辑)
            filter = Builders<BsonDocument>.Filter.Empty;
        }
        
        // ...原有数据读取、拼接逻辑不变(略)
    }
    else // CSV日期筛选核心逻辑(新增)
    {
        // ...原有CSV文件存在校验逻辑不变(略)
        foreach (var record in records)
        {
            // 筛选指定日期的数据(匹配CSV中Date字段,忽略时间)
            DateTime recordDate = DateTime.Parse(record.Date.ToString());
            if (!filterDate.HasValue || recordDate.Date == filterDate.Value.Date)
            {
                // ...原有数据拼接逻辑不变(略)
            }
        }
    }
}

  1. 提交事件适配(核心片段):修改btnSubmit_Click事件,添加日期参数传递逻辑,关联控件与筛选功能:

// 新增:根据CheckBox勾选状态,获取日期筛选参数(未勾选则为null)
DateTime? filterDate = chkFilterDate.Checked ? dtpFilterDate.Value : (DateTime?)null;
// 新增:调用GetDataAsync时传入日期参数(修改原有调用逻辑,适配筛选功能)
string rawData = await GetDataAsync(dataSource, csvPath, filterDate);

优化优势:新增功能不破坏原有代码逻辑,用户操作简单,可灵活切换筛选模式,适配更多生产数据分析场景,符合WinForms桌面应用的交互习惯。

2. Ollama API调用

核心配置

// 顶部集中配置(便于统一修改维护)
private readonly string _ollamaApiUrl = "http://localhost:11434/api/generate";
private readonly string _ollamaModel = "phi3:mini"; // 需与本地拉取的模型名完全一致
private readonly string _promptTemplate = @"请你分析以下原始数据集,并回答我的问题。
数据集:
{RawData}
我的问题:{UserQuestion}
回答要求:
1. 仅基于提供的数据集回答,不编造任何数据;
2. 必须分段输出,每个分析结论单独成段(用\n分隔);
3. 关键结论用数字编号列出,简洁明了,突出核心数据。";

调用方法(含异常处理+超时控制)

private async Task<string> CallOllamaApiAsync(string prompt)
{
    using (var httpClient = new HttpClient())
    {
        httpClient.Timeout = TimeSpan.FromSeconds(30); // 适配非计算密集型要求,避免超时
        var ollamaRequest = new
        {
            model = _ollamaModel,
            prompt = prompt,
            stream = false, // 桌面应用适配,一次性返回完整分析结果
            num_ctx = 2048, // 上下文窗口大小,小模型推荐2048,足够容纳数据集
            temperature = 0.1 // 低随机性,确保数据分析结果精准
        };
        try
        {
            // 发送POST请求调用Ollama API,ConfigureAwait(false)避免阻塞UI线程
            var response = await httpClient.PostAsJsonAsync(_ollamaApiUrl, ollamaRequest).ConfigureAwait(false);
            response.EnsureSuccessStatusCode(); // 校验请求是否成功,非200状态码抛异常
            // 解析API响应数据
            var ollamaResponse = await response.Content.ReadFromJsonAsync<OllamaResponse>().ConfigureAwait(false);
            // 判空处理,避免空引用报错
            return ollamaResponse?.Response ?? "未获取到AI分析结果,请检查模型是否正常运行。";
        }
        catch (HttpRequestException ex)
        {
            // 捕获网络、API调用相关异常,给出明确提示
            throw new Exception($"Ollama调用失败:{ex.Message},请检查:1.Ollama服务是否启动 2.模型{_ollamaModel}是否已拉取 3.端口11434是否被占用");
        }
    }
}
// 响应模型(字段大小写需与Ollama API返回格式完全一致,否则无法解析)
public class OllamaResponse
{
    [JsonPropertyName("response")]
    public string Response { get; set; }
    [JsonPropertyName("done")]
    public bool Done { get; set; } // 标记AI回答是否生成完成
}

3. 输出格式优化

解决AI回答无分段、格式混乱的问题,适配WinForms文本显示规则:

// 提交事件中处理换行符(WinForms需\r\n才能正确显示换行,AI返回为\n)
string aiAnswer = await CallOllamaApiAsync(finalPrompt);
string formattedAnswer = aiAnswer.Replace("\n", "\r\n"); // 替换换行符,确保分段显示
txtAnswer.Text = formattedAnswer;
// 进阶优化(可选):改用RichTextBox控件,支持加粗、颜色等更丰富的格式展示

五、关键优化点

  1. 动态配置:将数据库名、集合名、Prompt模板、Ollama配置等提取为类顶部的变量,集中管理,便于后续修改维护,无需修改核心业务逻辑。

  2. 异步处理:所有IO操作(读取MongoDB/CSV数据、调用Ollama API)均使用async/await异步语法,避免阻塞UI线程,防止界面卡死,提升用户体验。

  3. 数据量控制:MongoDB读取数据时添加Limit(50)分页限制,避免数据量过大导致Prompt过长,进而引发AI响应超时或内存溢出。

  4. 异常兜底:对用户空输入、网络错误、Ollama服务异常、文件不存在等场景做全面异常捕获,并给出清晰的错误提示,便于问题排查。

  5. 格式适配:通过Prompt强制AI输出分段文本,同时在代码中替换换行符,确保WinForms控件能正确渲染分段格式,提升结果可读性。

六、常见问题与解决方案

问题现象 原因 解决方法
找不到MongoClient类型 未安装MongoDB.Driver NuGet包,或未添加对应using指令 安装MongoDB.Driver包,并在代码顶部添加using MongoDB.Driver;
AI回答无分段/格式混乱 Prompt未明确格式要求,或换行符不兼容WinForms显示规则 优化Prompt强制要求分段,同时在代码中替换\n\r\n
调用Ollama提示「已取消一个任务」 Ollama服务停止、请求超时、11434端口被占用或数据量过大 1. 重启Ollama服务;2. 调高超时时间;3. 分页限制数据量;4. 检查11434端口是否被占用
Ollama拉取模型速度慢 网络环境不佳,默认镜像下载速度慢 临时切换国内镜像:终端执行set OLLAMA_MODELS=https://mirror.ai.tencent.com/ollama/models/,再拉取模型
CSV/MongoDB读取失败 CSV文件不存在、路径错误,或MongoDB数据库名/集合名输入错误 添加空值/路径校验,报错时提示具体错误信息,便于排查

七、核心注意事项

  1. Ollama模型名必须与代码中_ollamaModel完全一致(区分大小写),否则会导致模型调用失败。

  2. WinForms控件的Name属性需与代码中引用的名称完全一致,否则会报“未定义”错误,导致程序无法运行。

  3. 11434端口为Ollama默认端口,若被其他程序占用,可重启Ollama服务自动切换端口,或手动指定端口并同步修改代码中的API地址。

  4. Ollama模型拉取完成后,可离线运行,无需联网即可调用;离线使用前需确保模型已成功拉取。

  5. 大数据量场景需优先使用分页功能(如Limit(50)),避免Prompt过长导致AI响应超时或内存溢出。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐