Flutter + 本地大模型:实现一句话自然语言记账
2026/9/18 3:15:13 网站建设 项目流程

“记一笔账”这件事,看似简单,背后其实是一堆反人性的操作。打开记账App,找到分类、输金额、选账户、写备注,一套下来十几秒没了,坚持不了几天。所以当我把目光投向本地大模型和Flutter的时候,想法很简单:能不能直接输入一句“中午和黄经理吃饭,AA付了88”,让它自动结构化成一笔账单?这个项目我前前后后倒腾了三周,踩了不少坑,今天把完整思路和实现过程整理出来,给对“Flutter + 本地大模型”组合感兴趣的朋友做个参考。项目本身不算复杂,但把一个通用大模型在端侧落地成真正的工具,里头的水很深,值得好好聊。

这个项目的核心就三个关键词:Flutter(跨端UI)、本地大模型(隐私与离线)、自然语言记账(核心功能)。适合的人群也很明确:会一点Flutter但没碰过大模型工程化的客户端开发,或者想体验把AI塞进本地应用、又不想被云API绑架的个人开发者。接下来我从需求拆解开始,把每一步的思考、选型、实现和踩坑都摊开来说。

1. 需求拆解与方案选型:为什么“本地模型 + Flutter”是记账神器

1.1 从一句话记账到结构化账单:核心需求拆解

先聊最根本的问题:自然语言记账到底要解决什么?

常规记账App让人坚持不下去的痛点在于录入成本太高。那自然语言记账的体验应该是:用户像跟人说话一样,把一笔开销或收入口述出来,剩下的由程序自动处理。比如我随手输一句“昨天打车回家花了23块5”,理想情况下系统要提取出:

  • 方向:支出(expense)
  • 金额:23.5元
  • 分类:交通
  • 时间:昨天(实际日期由程序换算)
  • 备注:打车回家

这五个字段拆开看,前四个都有比较大的坑。“昨天”是一种相对时间表达,不能让模型输出字符串,得让它输出具体的日期;“23块5”是中文口语数字,不是“23.5”这种标准数字;“打车”到底算“交通”还是“出租”取决于你预设的分类体系;更麻烦的是“和黄经理吃饭,AA付了88”这种语序,金额和场景的关系需要理解才能正确处理。

如果沿用传统的关键词匹配加正则,就得维护一张庞大的关键词表,遇到“周三晚上团建聚餐人均70”这种句子直接崩溃,因为“人均”“团建”这种表达和直接金额没有显式对应关系。这就是我要引入大模型来处理的原因——自然语言解析本质上是一个语义理解问题,不是规则匹配问题

1.2 本地大模型 vs 云端大模型:数据隐私与成本的权衡

既然要引入大模型,第一个绕不开的选择是:用云端大模型API,还是在本地跑模型?

记账数据有天然的私密属性。虽然不是什么国家机密,但没人希望自己每天几点吃了什么、在哪儿消费了什么被上传到别人服务器上。即便是在安全合规的API服务上,处理这种高度个人化的数据,心里多少有些膈应。而且云端API是按token计费的,记账是个高频操作——如果坚持记账,一天三次、一年上千次请求,累计费用并不划算。

本地大模型刚好把这两块补上:

  • 隐私不出设备:数据在本地完成解析,不会外传
  • 推理零成本:模型跑在自己的机器或手机上,没有按次计费
  • 离线可用:没网也能记,特别适合地铁、飞机这类场景

代价也很实际:模型体积和推理速度。一个几B参数的量化模型需要几GB磁盘空间,在手机上推理一条短句也可能耗时几秒;在PC上部署则顺畅得多。所以这个项目我做了一个折中方案:模型用Ollama部署在PC上,Flutter应用通过局域网HTTP调用它;同时在代码层面上为以后在移动端直接接入端侧推理预留了接口

为了说清楚这个权衡,我做过一个对比:

维度云端大模型API本地大模型(PC部署)端侧模型(手机直跑)
隐私安全数据出设备数据不出局域网数据不出设备
单次耗时快,秒回中等,受电脑性能影响较慢,受手机算力影响
运行成本按token付费电费可忽略电费可忽略
网络依赖必须联网局域网即可完全离线
开发难度极低较高

1.3 模型选型与硬件门槛

模型选型是整个项目中最容易犯迷糊的地方。一开始我也犯过“越大越好”的错误,拉了个14B的模型,结果笔记本风扇起飞,解析一句话要等半分钟,体验稀碎。

后来我把选型思路调整为:能解决问题的最小模型

对记账这种任务,模型的输出是极其简短的一段JSON,不涉及长文本生成或者复杂推理,其实是个很轻量的任务。实测下来几款主流小模型表现都不错:

模型参数量量化后体积一句话解析耗时(CPU推理)中文理解
Qwen2.5-1.5B1.5B约1.2GB2-4秒优秀
Qwen2.5-3B3B约2.2GB4-7秒更优
Llama 3.2-1B1B约0.9GB1-3秒够用
Phi-3-mini3.8B约2.4GB5-8秒良好

这里要补充一句,如果你没有老显卡、主要靠CPU推理,优先选1.5B-3B这个档位的模型,既能保证语义理解,也不会让用户等得崩溃。如果在手机端直接跑,建议选1B-2B的量化模型,配合llama.cpp或ExecuTorch这类端侧推理框架。我这次PC端演示使用的是Qwen2.5-3B,准确率比1.5B高不少,耗时还在可接受范围内。

2. 环境准备:Flutter工具链与本地模型部署

2.1 Flutter SDK 与 FVM 多版本管理

写项目之前先搭环境。Flutter的安装网上教程汗牛充栋,这里说一下我踩到的两个关键点。

第一,强烈建议用FVM管理Flutter SDK版本。热词里有“fvm安装多版本flutter”,这是一个过来人才会明白的痛点。Flutter的升级节奏很快,你的老项目可能还在用3.16,新项目已经要3.24了。以前我是直接下载SDK压缩包到自定义目录,每次切换就改PATH,麻烦且容易出幺蛾子。用FVM之后舒服太多:

# 安装FVM(通过Homebrew或pub) brew install fvm # 安装指定版本的Flutter fvm install 3.24.0 # 项目根目录指定版本 fvm use 3.24.0 # 查看当前Flutter版本 fvm flutter --version

FVM会为每个项目记录一份.fvmrc配置文件,团队协作时大家各自执行fvm install就自动切换到项目指定的版本,彻底告别“在我电脑上能跑”的魔咒。

第二,第一次执行flutter doctor的时候,耐心把Android SDK、Xcode、Chrome这些依赖项都补齐。通常首次跑 Flutter 项目,真正的拦路虎不是Flutter本身,而是Android的Gradle网络问题。国内环境下载Gradle依赖经常失败,一般需要在android/build.gradle里改成阿里云镜像,或者在gradle-wrapper.properties里改distributionUrl。我建议先跑一个空项目,把环境链路走通,再开始写业务代码。

Flutter本身是跨平台框架,我这个项目最终目标是手机端能用,所以开发阶段主要在Chrome和Android模拟器上调试。这里多提一句热词里的“flutter现在主流开发用什么编译器”,现在主流还是 Android Studio 或 VS Code。我日常用 VS Code,装 Flutter 和 Dart 插件就够了,启动快、内存占用小,调试和热重载用起来非常顺手。

2.2 本地大模型部署:Ollama 一行命令拉起推理服务

本地大模型的部署方案选择上,我用的是Ollama。没有选 llama.cpp 直接编译,也没有上 Dify 这类重工具链,原因只有两个字:省心。

Ollama 把模型管理、量化、推理服务打包得非常友好,基本是“装完就能用”的体验。安装也很简单,官网下载对应平台的安装包,或者用一行命令:

# macOS 或 Linux curl -fsSL https://ollama.com/install.sh | sh # 启动服务(Ollama 默认常驻后台) ollama serve # 拉取模型并运行 ollama pull qwen2.5:3b

模型拉下来之后,Ollama 会默认监听http://localhost:11434,通过 REST API 对外提供推理服务。验证一下服务是否正常:

curl http://localhost:11434/v1/models

能看到模型列表,就说明服务已经跑起来了。Ollama 还兼容 OpenAI 的API格式,意味着后续要切到任何 OpenAI 兼容的云端服务,代码几乎不用改。

这里再顺带澄清一个容易混淆的点:如果要在局域网里让手机上的Flutter App访问这台电脑的Ollama,光ollama serve默认只监听本机回环地址,需要让它监听局域网地址。可以设置环境变量:

# 监听所有网卡地址 OLLAMA_HOST=0.0.0.0:11434 ollama serve

此时手机和电脑连同一个Wi-Fi,App里请求http://<电脑局域网IP>:11434就可以访问。这一点很多人第一次搞会踩坑,以为模型部署好了App却怎么都连不上,其实问题就出在监听地址上。

2.3 用 Dify、LangChain 还是直接调 HTTP?

我注意到热词里有“dify使用ollama设置本地大模型”。Dify 是一个非常优秀的 LLM 应用开发平台,可以做工作流编排、RAG、Agent等,但我的场景只是“一个输入文本到一个JSON输出”的轻量转换,引入 Dify 这种重量级平台反而增加了部署复杂度。

我的判断是:

  • 如果目标是快速构建原型,直接调 Ollama 的 HTTP API 就够了
  • 如果要给应用加上多轮对话、知识库、复杂的Agent行为,再考虑 Dify
  • LangChain 同理,它的核心是组合各种工具链做复杂编排,对我的场景是多余依赖

架构上追求简单,意味着后期排查问题更轻松。我们是要做一个记账工具,不是做一个大模型平台。所以我的实际选择是:Flutter App 直接通过 HTTP 和 Ollama 通信,中间不加任何中转层。

3. 核心架构设计:Flutter 如何与本地大模型协作

3.1 整体架构与数据流

开始写代码之前,先把整个应用的数据流理清楚:

用户输入一句话 ↓ Flutter 界面获取文本 ↓ Dart HTTP 客户端发送请求到 Ollama(携带 Prompt 和 JSON Format 约束) ↓ Ollama 完成本地推理,返回结构化 JSON 文本 ↓ Flutter 解析 JSON ↓ Dart 层做兜底规则校验(金额非零、分类存在性、时间归一化) ↓ 写入 SQLite 本地数据库 ↓ 刷新首页账单列表

这个链路是单向的、清晰的,没有复杂的双向绑定,也没有消息队列。整个项目的核心就两个难点:一是让模型稳定吐出结构合格的JSON,二是把模型输出安全准确地转换并写入本地库。

3.2 Flutter 多线程与异步:别让推理卡住UI

Flutter 的UI是单线程模型,但网络请求和JSON解析这种耗时操作不能放在主Isolate里跑,否则界面会直接卡死。尤其JSON解析在Dart里虽然快,处理一个模型输出的几百字节不是问题,但HTTP请求的时间可能长达两三秒,这块必须异步化。

我的处理策略是:

  1. HTTP请求交由http包的异步方法执行,它内部自己处理I/O,不会阻塞UI。
  2. 解析模型输出用computeIsolate.run,把结构化JSON解析和规则校验放在后台Isolate执行,避免在主Isolate做大量字符串运算。
  3. 状态变更通过 ValueNotifier / Stream 通知界面刷新,不在setState里做任何耗时逻辑。

顺带提一个 Flutter 多线程的进阶玩法。如果你以后想把模型直接跑到手机端里,比如用ExecuTorchllama.cpp的Flutter插件,推理过程本身就是纯CPU计算密集型任务,必须放到独立Isolate,不然哪怕只推理一秒钟,UI也会掉帧卡顿。Flutter 的Isolate.runcompute在这种场景就特别好用,代码几乎不用大改:

final result = await Isolate.run(() { return parseAndValidate(rawText, categories); });

3.3 数据存储与本地化:SQLite 与账单表设计

数据存储我用了sqflite插件,它适配 Android、iOS、macOS、Windows 和 Linux,桌面端可以直接用同样的代码。本地数据最大的好处是隐私可控,且导出方便,不依赖任何云服务。

表结构设计上,我保持精简:

CREATE TABLE records ( id INTEGER PRIMARY KEY AUTOINCREMENT, direction TEXT NOT NULL, -- expense / income amount_cents INTEGER NOT NULL, -- 金额以“分”为单位存储,避免浮点误差 category TEXT NOT NULL, -- 餐饮 / 交通 / 购物 / 工资 ... note TEXT, -- 原始备注或模型生成的摘要 record_time INTEGER NOT NULL, -- 记账时间,Unix时间戳 created_at INTEGER NOT NULL );

金额为什么不直接存浮点数?记账涉及钱,浮点误差是绝对不能接受的。0.1 + 0.2在二进制浮点里不等于0.3,一旦涉及统计报表就会出大问题。所以我的做法是:模型输出“23.5”,Dart 解析后乘以100,得到2350(分),所有统计计算都在整数域进行,到了展示层再除以100转回元。这是记账类应用最基本的一条原则。

分类字段我预设了一套精简的一级分类,比如餐饮、交通、购物、居住、娱乐、医疗、人情、工资、理财等。模型的作用是识别语义,Dart侧再做一个“分类归一化”映射,把模型可能输出的近义分类(比如“烧烤”“外卖”“聚餐”)映射回预设体系里。

4. 自然语言解析核心实现:从口语到结构化 JSON

4.1 结构化输出的关键:JSON 模式与约束

这一步是整篇文章的重头戏,也是我花了最多时间调优的地方。

大模型默认是内容生成器,它会把“今天中午和黄经理吃饭,AA付了88”这种输入,很自然地回复一长串解释:“好的,根据您提供的信息,这是一笔支出……”。如果每个请求都返回一堆废话,后续就没法处理。

好在 Ollama 提供了一个非常实用的参数叫format。把format设置成"json"之后,模型会被强制输出一个合法的JSON对象,不会再产生额外解释文字。这个约束对结构化任务来说等于把路铺好了,基本消灭了解析不到数据的尴尬情况。

请求的大致样子:

{ "model": "qwen2.5:3b", "messages": [ {"role": "system", "content": "你是记账助手,从口语中提取结构化账单。"}, {"role": "user", "content": "今天中午和黄经理吃饭,AA付了88"} ], "format": "json", "stream": false, "temperature": 0.1 }

stream设为 false 是让服务端一次性返回完整结果;temperature设为0.1是让输出尽量稳定、确定,避免返回的结果每次都不一样的“幻觉式抖动”。

4.2 提示词工程:如何让模型稳定输出

光有format: json还不够,如果不在系统提示词里明确要求字段结构,模型会随便给你一个它以为合理的JSON,字段名千奇百怪。所以我用了一个比较完整的 System Prompt,把输出Schema、字段含义、枚举值和几个示例都写进去:

你是一个记账助手。用户会输入一段描述收支的自然语言。 要求: 1. 只输出JSON对象,不要任何多余文字。 2. JSON字段说明: direction: 取值为 "expense" 或 "income" amount: 数字,表示人民币金额(元),精确到小数点后两位 category: 从以下分类中选择一个:餐饮, 交通, 购物, 居住, 娱乐, 医疗, 人情, 工资, 理财, 其他 note: 字符串,一句话总结这笔收支内容 time: 字符串,这笔收支发生的日期,格式为 YYYY-MM-DD,相对今天计算 3. 示例: 用户输入:今天中午和黄经理吃饭,AA付了88 输出:{"direction": "expense", "amount": 88.00, "category": "餐饮", "note": "和黄经理吃饭AA", "time": "2024-12-08"} 用户输入:收到6月工资15000 输出:{"direction": "income", "amount": 15000.00, "category": "工资", "note": "6月工资", "time": "2024-12-08"} 当前日期:2024-12-08

注意我在最后显式传入了“当前日期”。为什么不直接用相对时间让模型输出“今天”?因为JSON输出要求标准化日期,模型并不知道“今天”对应的具体是哪一天。把当前日期作为上下文给进去,它才能把“昨天”“上周三”这类表达换算成正确的YYYY-MM-DD

这段Prompt在实测中效果提升非常明显。一开始没有 few-shot 示例时,模型偶尔会把“收到”误判成支出,或者把时间省略;加入两个示例后输出质量稳定了很多。

4.3 Dart 端解析与兜底逻辑

即使有 format 约束,模型偶尔也会抽风,比如字段名拼错、金额写成字符串、方向值写错。所以我的 Dart 侧解析逻辑不能直接jsonDecode了事,而是要加一层“宽容解析 + 兜底校验”。

具体的处理顺序:

  1. 先尝试直接解码jsonDecode拿到Map。
  2. 字段名兼容:如果direction不存在,尝试typeexpense_type等;如果amount缺失,尝试money等。
  3. 类型修复amount可能是字符串"88",要转成numdirection如果是"支出",要映射成"expense"
  4. 规则校验:金额必须大于0,分类必须存在于预设列表,时间必须是合法日期。
  5. 兜底处理:如果校验失败,退化为“人工确认”模式——把模型返回的原始文本展示给用户,让用户手动改字段。

第5步极其重要。做一个依赖模型解析的工具,你永远要对模型的不确定性保留一条退路。如果直接信任模型的输出写入数据库,某个数据异常可能让后续所有统计全部错位。我的经验是把它当作“半自动标注工具”——绝大多数时候模型是对的,偶尔失败时人工一秒钟就改好,体验依然远好于全手填。

下面是我封装的一个解析核心片段:

class BillParser { static BillRecord parseModelOutput(String modelRawText, List<String> categories) { try { final Map<String, dynamic> raw = jsonDecode(modelRawText) as Map<String, dynamic>; final String direction = normalizeDirection(raw['direction']); final double amount = double.tryParse(raw['amount'].toString()) ?? 0; final String category = normalizeCategory(raw['category'], categories); final String note = (raw['note'] ?? '').toString(); final String time = normalizeTime(raw['time']); if (amount <= 0) throw const FormatException('金额不合法'); if (direction != 'expense' && direction != 'income') throw const FormatException('方向不合法'); return BillRecord( direction: direction, amountCents: (amount * 100).round(), category: category, note: note, recordTime: DateTime.parse(time), ); } catch (e) { throw const FormatException('模型输出无法解析,需要人工确认'); } } }

5. 实操环节:从空白项目到能跑的记账应用

5.1 创建 Flutter 项目与依赖管理

环境就绪之后,创建项目本身很快:

fvm flutter create natural_language_bookkeeping cd natural_language_bookkeeping

然后把依赖写进pubspec.yaml

dependencies: flutter: sdk: flutter http: ^1.2.1 sqflite: ^2.3.3 path: ^1.9.0 provider: ^6.1.2 intl: ^0.19.0
  • http用于发请求给 Ollama
  • sqflite负责本地数据库
  • provider做状态管理
  • intl做日期格式化

5.2 编写模型请求服务层

Flutter 侧请求 Ollama 的核心逻辑,无非是封装一个ApiClient

class LlmClient { final String baseUrl; final String model; LlmClient({required this.baseUrl, required this.model}); Future<Map<String, dynamic>> chat(String userInput, {required String systemPrompt, required String today}) async { final messages = [ {'role': 'system', 'content': systemPrompt}, {'role': 'user', 'content': userInput}, ]; final resp = await http.post( Uri.parse('$baseUrl/v1/chat/completions'), headers: {'Content-Type': 'application/json'}, body: jsonEncode({ 'model': model, 'messages': messages, 'format': 'json', 'stream': false, 'temperature': 0.1, }), ); if (resp.statusCode == 200) { final data = jsonDecode(resp.body) as Map<String, dynamic>; final content = data['choices'][0]['message']['content'] as String; return jsonDecode(content) as Map<String, dynamic>; } throw Exception('HTTP ${resp.statusCode}: ${resp.body}'); } }

这里注意我用的路径是/v1/chat/completions,这是 Ollama 兼容 OpenAI 接口的路径,好处是以后换云服务商只需要改baseUrl,请求体和响应结构的处理代码完全复用。

5.3 界面与状态管理

界面我做了三个模块:输入区、历史账单列表、解析确认弹窗。

输入区最核心的交互是“先解析,后确认”。用户输入一句话,点“智能记账”按钮,App 先发请求给本地模型,拿到候选JSON后弹出一个确认卡片,显示“方向:支出 / 金额:88 / 分类:餐饮 / 时间:今天 / 备注:和黄经理吃饭AA”,用户确认后写入数据库。如果解析失败,就弹出一个带输入框的修正卡片,让用户手动修改。

为什么一定要加“确认”这一步?因为模型永远有出错概率,对于记账这种数据敏感的场景,写入即终态,错了再改成本很高。确认步骤把错误拦截在写入之前,是最既保证效率又保证准确率的方式。

状态管理用的 Provider,按模块拆了几个 ChangeNotifier:

  • SettingsViewModel:管理服务地址、模型名称等配置
  • RecordListViewModel:账单列表的加载、增删
  • ParseViewModel:管理解析中、解析成功、解析失败的状态

5.4 端到端实测

项目跑通后,我拿一批真实口语做了测试,结果如下:

输入语句方向金额分类时间识别
今天中午和黄经理吃饭,AA付了88expense88.00餐饮准确
打车去机场,花了45块3expense45.30交通准确
收到6月工资15000income15000.00工资准确
上周三超市买牛奶鸡蛋,花了我59.9expense59.90购物准确
地铁充值50expense50.00交通准确

这个准确率已经达到可以日常使用的水平。偶尔失败的情况集中在“表情夸张、带反讽”的语句上,比如“今天可真是破财,手机屏摔碎换屏花了800”,这种带情绪的句子模型偶尔会把分类判断成“娱乐”。遇到这种情况我的兜底逻辑就直接弹人工确认页,手动选一下分类就完事,不会对使用造成太大阻碍。

6. 常见问题与避坑实录

6.1 连接不上 Ollama:IP、端口与防火墙问题

这个问题出现的频率最高。App 端报错通常是Connection refused或者SocketException

排查顺序我给整理成了速查表:

现象可能原因解决办法
电脑本机 curl 通,手机连不上Ollama 只监听了127.0.0.1设置OLLAMA_HOST=0.0.0.0:11434并重启
手机和电脑能 ping 通但请求超时防火墙拦截了11434端口放行 TCP 11434 端口
App 里能请求但返回404请求路径错了确认是/v1/chat/completions
请求成功但响应特别慢模型太大,CPU推理吃力换更小模型或开启量化层

特别提醒一点,如果手机和电脑不在同一个网段,哪怕连同一个Wi-Fi也可能被AP隔离,这时候只能改网络配置或者用USB端口转发调试,这个坑也值得提前知道。

6.2 模型吐出的 JSON 不稳定怎么办

即便开了format: json,偶尔也有小概率出现字段缺失、金额带单位(比如“88元”)、分类超出范围的情况。我的处理方式是多层保险:

  1. Prompt 里写死 Schema 和枚举,并给两个 few-shot 例子。
  2. temperature调到0.1,尽量让输出模式稳定。
  3. Dart 侧做字段名兼容映射,对“支出/收入”这类中文词做方向归一化。
  4. 兜底人工确认,一切都失败就退化为手动表单。

其中最有效的是第1条。Prompt 里的输出示例直接影响模型模仿的格式,好的示例比你在提示词里写十句“不要输出多余内容”都管用。这个技巧在AI圈叫few-shot prompting,一种性价比极高的调优手段。

6.3 Flutter 编译与运行时的性能坑

热词里有“flutter impeller”和“flutter 多线程”,这块我也踩到过。Impeller 是 Flutter 新渲染引擎,用iOS测试的时候,如果遇到文字模糊或某些着色器导致掉帧,可以在Info.plist里关掉它应急,但新版本 Flutter 默认开启已经没太大问题。

更重要的性能坑在多线程上。我最初是直接在await http.post返回后,立刻在主Isolate里执行jsonDecode和规则校验。当模型输出有几百个字段或者做了十几条批量解析时,页面明显掉帧。后来把所有非UI逻辑挪进Isolate.run,体验立刻顺滑了很多。如果后续要接入端侧推理,这一步更是不可避免的。

另外热词里提到“flutter 低功耗蓝牙 ios 有问题嘛”,这跟本主题无关,但提醒我一点:Flutter 端做硬件相关功能,iOS 的系统限制往往比 Android 严格,调试时尽量先跑 Android 再移植 iOS,能省很多时间。

6.4 数据准确率还能怎么提升

如果你发现模型解析准确率还不够,优先做两件事:

第一,扩充 few-shot 示例。把识别错误的语句和对应的正确JSON写进 Prompt,作为新的示例,让模型在推理时参考。这招对提升准确率非常直接。比如我一开始发现“AA制”经常识别成“人情”,添加示例后基本不再出错。

第二,做一次基于本地数据的微调(LoRA)。如果你有一份个人历史账单,可以把“口语描述 → 结构化JSON”的pair整理成数据集,用LoRA微调一个小模型。这个方向我还在摸索期,但本地微调已经是当前很有价值的赛道,值得投入。

最后的一点心得

整个项目从零到跑通,最深的体会是:大模型应用开发的难点不在“调通API”,而在于对不完美输出的系统容错设计。Prompt没有绝对的对错,只有效果好坏;模型输出的JSON不是数据库里可以直接信任的数据,必须经过一层“人机协作”流程把不确定性消化掉。Flutter 在这个项目里扮演的是壳和交互层,它的跨平台能力、Isolate并发模型和丰富的插件生态,让我可以用一套代码同时打通桌面端和移动端,省掉了太多重复劳动。如果你也想试试“本地大模型 + Flutter”这个组合,建议从今天说的这句“今天中午和黄经理吃饭,AA付了88”开始,做一个自己的自然语言记账工具。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询