Flutter AI 訪問多個(gè)AI 模型
現(xiàn)在網(wǎng)上有很多大模型AI绿语,我們可能也可以嘗試很多種模型所以我將我們的程序進(jìn)行了改造谢翎,增加了工廠模式來適配各種類型的API
我創(chuàng)建了一個(gè) AIProvider 工廠類瀑晒,它根據(jù)給定的類型返回相應(yīng)的 AI 服務(wù)實(shí)例。AIProvider 類中的 getAI 方法接受一個(gè)字符串類型的參數(shù),表示要返回的 AI 服務(wù)類型赚瘦。在 _fetchReplyFromAI 方法中,我使用 AIProvider 工廠類來獲取 ChatGPT 服務(wù)實(shí)例奏寨,并使用它來獲取回復(fù)消息起意。這樣你就可以很容易地添加新的 AI 服務(wù)類型,而不必更改調(diào)用方的代碼病瞳。
我現(xiàn)在 以O(shè)penAI 為例
之后我會(huì)增加百度的文心一言揽咕、阿里的通義千問
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(ChatApp());
}
class ChatApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ChatGPT Demo',
theme: ThemeData(
primaryColor: Colors.blue,
),
home: ChatScreen(),
);
}
}
class ChatScreen extends StatefulWidget {
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final TextEditingController _textController = TextEditingController();
final List<Message> _messages = [];
// 創(chuàng)建一個(gè)AIProvider工廠實(shí)例
final AIProvider _aiProvider = AIProvider();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('ChatGPT Demo'),
actions: [IconButton(icon: Icon(Icons.settings), onPressed: () {})],
),
body: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(16.0),
),
margin: EdgeInsets.all(16.0),
padding: EdgeInsets.all(16.0),
child: Column(
children: [
Expanded(
child: ListView.builder(
reverse: true,
itemCount: _messages.length,
itemBuilder: (BuildContext context, int index) {
return _buildMessage(_messages[index]);
},
),
),
SizedBox(height: 8.0),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
children: [
IconButton(icon: Icon(Icons.settings), onPressed: () {}),
SizedBox(width: 8.0),
Expanded(
child: TextField(
controller: _textController,
decoration: InputDecoration(
hintText: 'Send a message',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
),
),
),
SizedBox(width: 8.0),
IconButton(
icon: Icon(Icons.send),
onPressed: () => _handleSubmitted(_textController.text),
),
],
),
),
SizedBox(height: 8.0),
],
),
),
);
}
Widget _buildMessage(Message message) {
final isUserMessage = !message.isBot;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Column(
crossAxisAlignment: isUserMessage ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: isUserMessage ? MainAxisAlignment.end : MainAxisAlignment.start,
children: [
CircleAvatar(
child: isUserMessage ? Icon(Icons.person) : Icon(Icons.android),
),
SizedBox(width: 8.0),
Text('Name'),
],
),
SizedBox(height: 4.0),
Container(
padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0),
decoration: BoxDecoration(
color: isUserMessage ? Colors.blue : Colors.white,
borderRadius: BorderRadius.circular(8.0),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 1,
blurRadius: 3,
offset: Offset(0, 2),
),
],
),
child: Text(message.text),
),
],
),
);
}
void _handleSubmitted(String text) {
_textController.clear();
setState(() {
_messages.insert(0, Message(text, isBot: false));
});
_fetchReplyFromAI(text);
}
Future<void> _fetchReplyFromAI(String message) async {
try {
final reply = await _aiProvider.getAI('ChatGPT').fetchReply(message);
setState(() {
_messages.insert(0, Message(reply, isBot: true));
});
} catch (e) {
print('Error: $e');
// 處理錯(cuò)誤情況
}
}
}
class Message {
final String text;
final bool isBot;
Message(this.text, {this.isBot = false});
}
// AIProvider工廠類
class AIProvider {
AIProvider();
// 根據(jù)類型返回相應(yīng)的AI服務(wù)實(shí)例
AI getAI(String type) {
if (type == 'ChatGPT') {
return ChatGPTService('YOUR_CHATGPT_API_URL', 'YOUR_API_KEY');
} else {
throw Exception('Unsupported AI type');
}
}
}
// 抽象AI接口
abstract class AI {
Future<String> fetchReply(String message);
}
// ChatGPT服務(wù)類
class ChatGPTService implements AI {
final String apiUrl;
final String apiKey;
ChatGPTService(this.apiUrl, this.apiKey);
@override
Future<String> fetchReply(String message) async {
final headers = {
'Content-Type': 'application/json; charset=utf-8',
'Authorization': 'Bearer $apiKey',
};
final body = jsonEncode({'message': message});
try {
final response = await http.post(Uri.parse(apiUrl), headers: headers, body: body);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return data['reply']; // 假設(shè)服務(wù)器返回的數(shù)據(jù)中有一個(gè)名為'reply'的字段悲酷,表示回復(fù)消息
} else {
throw Exception('Failed to fetch reply from ChatGPT API');
}
} catch (e) {
print('Error: $e');
// 處理錯(cuò)誤情況
return 'Error';
}
}
}