1. 项目概述与背景
作为一名长期从事跨平台应用开发的工程师,我最近在重构个人AI助手项目时,基于Flutter 3.32.8和硅基流动API实现了一套轻量级的AI对话系统。这个方案特别适合需要快速集成智能对话功能的中小型应用,相比直接使用大厂闭源SDK,这种方案具有以下优势:
- 代码完全可控,无需依赖第三方SDK版本更新
- 可灵活切换不同AI服务提供商的后端
- 客户端实现仅需约200行Dart代码
- 支持全平台运行(iOS/Android/Web/Desktop)
核心功能架构分为三层:
- 表现层:Flutter界面组件
- 逻辑层:Dart实现的对话管理
- 服务层:硅基流动API通信
注意:本文示例代码已脱敏处理,实际使用时需要替换为自己的API密钥和服务地址。建议不要在客户端直接硬编码密钥,应采用安全的密钥管理方案。
2. 环境准备与基础配置
2.1 Flutter环境要求
确保开发环境满足:
bash复制flutter --version # 输出应为3.32.8或更高
dart --version # 需要3.2.0+
在pubspec.yaml中添加依赖:
yaml复制dependencies:
http: ^1.1.0 # API请求
dio: ^5.3.3 # 高级HTTP客户端
flutter_tts: ^3.6.3 # 文字转语音
speech_to_text: ^6.6.0 # 语音转文字
2.2 硅基流动API配置
创建api_config.dart保存密钥配置:
dart复制class AIConfig {
static const String model = "silicon-flow-pro";
static const double temperature = 0.7;
static const String baseUrl = "https://api.siliconflow.ai/v1";
static const String apiKey = "sk-your-actual-key";
static const Map<String, String> headers = {
"Content-Type": "application/json",
"Authorization": "Bearer $apiKey"
};
}
重要安全提示:实际项目中应该:
- 使用环境变量存储密钥
- 或通过后端服务中转API调用
- 禁止将密钥提交到版本控制系统
3. 核心功能实现
3.1 基础对话功能实现
创建chat_service.dart处理AI通信:
dart复制import 'dart:convert';
import 'package:http/http.dart' as http;
class ChatService {
static Future<String> sendMessage(String message) async {
final response = await http.post(
Uri.parse('${AIConfig.baseUrl}/chat/completions'),
headers: AIConfig.headers,
body: jsonEncode({
'model': AIConfig.model,
'temperature': AIConfig.temperature,
'messages': [
{'role': 'user', 'content': message}
]
}),
);
if (response.statusCode == 200) {
return jsonDecode(response.body)['choices'][0]['message']['content'];
} else {
throw Exception('API请求失败: ${response.statusCode}');
}
}
}
UI层调用示例:
dart复制TextField(
onSubmitted: (text) async {
final response = await ChatService.sendMessage(text);
setState(() => messages.add(response));
},
)
3.2 语音交互功能实现
语音转文字(STT)
dart复制import 'package:speech_to_text/speech_to_text.dart';
class SpeechService {
final _speech = SpeechToText();
Future<String> recognize() async {
if (!await _speech.initialize()) {
throw Exception('语音识别初始化失败');
}
String result = '';
await _speech.listen(
onResult: (val) => result = val.recognizedWords,
listenFor: Duration(seconds: 30),
);
return result;
}
}
文字转语音(TTS)
dart复制import 'package:flutter_tts/flutter_tts.dart';
class TTSService {
final _tts = FlutterTts();
Future<void> speak(String text) async {
await _tts.setLanguage('zh-CN');
await _tts.setPitch(1.0);
await _tts.speak(text);
}
}
4. 完整应用集成
4.1 状态管理方案
推荐使用Riverpod管理对话状态:
dart复制final chatProvider = StateNotifierProvider<ChatNotifier, List<Message>>((ref) {
return ChatNotifier();
});
class ChatNotifier extends StateNotifier<List<Message>> {
ChatNotifier() : super([]);
Future<void> sendMessage(String text) async {
state = [...state, Message(user: text, isMe: true)];
final response = await ChatService.sendMessage(text);
state = [...state, Message(user: response, isMe: false)];
}
}
4.2 完整页面示例
dart复制class ChatPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final messages = ref.watch(chatProvider);
return Scaffold(
appBar: AppBar(title: Text('AI对话')),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: messages.length,
itemBuilder: (_, i) => ChatBubble(
text: messages[i].text,
isMe: messages[i].isMe,
),
),
),
MessageInput(
onSend: (text) => ref.read(chatProvider.notifier).sendMessage(text),
),
],
),
floatingActionButton: VoiceButton(
onRecognized: (text) => ref.read(chatProvider.notifier).sendMessage(text),
),
);
}
}
5. 性能优化与调试技巧
5.1 对话流式响应
修改ChatService支持流式响应:
dart复制import 'package:dio/dio.dart';
Stream<String> streamChat(String message) async* {
final dio = Dio();
final response = await dio.post(
'${AIConfig.baseUrl}/chat/completions',
options: Options(headers: AIConfig.headers),
data: {
'model': AIConfig.model,
'stream': true,
'messages': [{'role': 'user', 'content': message}]
},
onReceiveProgress: (_, __) {},
);
final stream = response.data.asBroadcastStream();
await for (var chunk in stream) {
yield chunk.toString();
}
}
5.2 常见问题排查
-
API返回403错误
- 检查API密钥是否正确
- 验证服务地址是否包含版本号(如/v1)
- 确认账号是否有足够配额
-
语音识别无响应
- Android需要手动申请录音权限
- iOS需要在Info.plist添加NSMicrophoneUsageDescription
- 真机测试时检查麦克风是否被其他应用占用
-
跨平台渲染差异
- Web端需要额外配置CORS
- macOS需要启用音频输入权限
- 使用flutter_platform_widgets处理平台差异
6. 扩展功能建议
- 对话上下文管理
dart复制class Conversation {
final List<Map<String, String>> _history = [];
void addMessage(String role, String content) {
_history.add({'role': role, 'content': content});
if (_history.length > 10) _history.removeAt(0);
}
List<Map<String, String>> get history => List.from(_history);
}
- 本地缓存实现
dart复制import 'package:hive/hive.dart';
class ChatCache {
static final _box = Hive.box('chat_history');
static void save(String query, String response) {
_box.add({'time': DateTime.now(), 'query': query, 'response': response});
}
static List<Map> get history => _box.values.toList().cast<Map>();
}
- 自定义温度参数
dart复制Slider(
value: temperature,
min: 0.1,
max: 1.0,
onChanged: (v) => setState(() => temperature = v),
label: '创造性: ${temperature.toStringAsFixed(1)}',
)
在实际项目开发中,我发现Flutter与AI服务的结合需要注意几个关键点:首先是网络请求的稳定性处理,需要做好重试机制;其次是语音功能的平台差异,需要针对每个平台进行测试;最后是对话状态的持久化,建议采用本地缓存+定期同步的方案。