Flutter AI 訪問多個(gè)AI 模型
在上一篇中我們構(gòu)建了一個(gè)可以訪問多模型聊天應(yīng)用京腥,現(xiàn)在設(shè)置菜單可以選擇不同的大模型
因?yàn)榇a較多肉瓦,沒有將所有代碼貼出(也沒有上傳GitHub)如果有需要在在評論區(qū)留言,我會更新文章或者上傳代碼
模型選擇
我創(chuàng)建了一個(gè)名為 _showPopupMenu 的函數(shù),在用戶點(diǎn)擊 IconButton 時(shí)調(diào)用該函數(shù),然后使用 showMenu 函數(shù)顯示一個(gè)類似于 PopupMenuButton 的菜單臣嚣。用戶選擇了某個(gè) AI 類型后會更新標(biāo)題和相應(yīng)的 AI 服務(wù)實(shí)例。
我增加一個(gè) _showAISelectionMenu 方法
寫法 1
void _showAISelectionMenu(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
child: Wrap(
children: <Widget>[
ListTile(
leading: Icon(Icons.chat),
title: Text('ChatGPT'),
onTap: () {
setState(() {
_appBarTitle = 'ChatGPT'; // 更新標(biāo)題
_aiProvider = AIProvider(type: 'ChatGPT'); // 更新 AIProvider
});
Navigator.pop(context);
},
),
ListTile(
leading: Icon(Icons.android),
title: Text('文心一言'),
onTap: () {
setState(() {
_appBarTitle = '文心一言'; // 更新標(biāo)題
_aiProvider = AIProvider(type: 'ErnieBot'); // 更新 AIProvider
});
Navigator.pop(context);
},
),
ListTile(
leading: Icon(Icons.question_answer),
title: Text('通義千問'),
onTap: () {
setState(() {
_appBarTitle = '通義千問'; // 更新標(biāo)題
_aiProvider = AIProvider(type: 'QwenBot'); // 更新 AIProvider
});
Navigator.pop(context);
},
),
// 添加更多的 AI 類型
],
),
);
},
);
}
//...
}
這樣寫方法中重復(fù)代碼太多了剥哑,我將 AI 類型和對應(yīng)的標(biāo)題定義為兩個(gè)列表 aiTypes 和 aiTitles硅则。然后在 _showAISelectionMenu 方法中使用 ListView.builder 來遍歷這兩個(gè)列表,生成對應(yīng)的 ListTile 列表株婴。同時(shí)怎虫,我添加了一個(gè)輔助方法 _buildIcon 來根據(jù) AI 類型生成對應(yīng)的圖標(biāo)。這樣可以減少重復(fù)的代碼困介,并使代碼更加清晰易讀大审。
寫法 2
void _showAISelectionMenu(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
child: ListView.builder(
itemCount: aiTypes.length,
itemBuilder: (BuildContext context, int index) {
String aiType = aiTypes[index];
String aiTitle = aiTitles[index];
return ListTile(
leading: _buildIcon(aiType),
title: Text(aiTitle),
onTap: () {
setState(() {
_appBarTitle = aiTitle; // 更新標(biāo)題
_aiProvider = AIProvider(type: aiType); // 更新 AIProvider
});
Navigator.pop(context);
},
);
},
),
);
},
);
}
Widget _buildIcon(String aiType) {
switch (aiType) {
case 'ChatGPT':
return Icon(Icons.chat);
case 'ErnieBot':
return Icon(Icons.android);
case 'QwenBot':
return Icon(Icons.question_answer);
default:
return Icon(Icons.help);
}
}
final List<String> aiTypes = ['ChatGPT', 'ErnieBot', 'QwenBot'];
final List<String> aiTitles = ['ChatGPT', '文心一言', '通義千問'];
具體模型選擇
寫法 1
class _ChatScreenState extends State<ChatScreen> {
final TextEditingController _textController = TextEditingController();
final List<Message> _messages = [];
AIProvider _aiProvider = AIProvider();
String _appBarTitle = 'ChatGPT'; // 初始標(biāo)題
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_appBarTitle),
actions: [
IconButton(
icon: Icon(Icons.settings),
onPressed: () {
_showPopupMenu(context);
},
),
],
),
body: Container(
//...
),
);
}
void _showPopupMenu(BuildContext context) async {
final selectedValue = await showMenu<String>(
context: context,
position: RelativeRect.fromLTRB(100, 100, 0, 100), // 根據(jù)需要調(diào)整位置
items: [
PopupMenuItem<String>(
value: 'ChatGPT',
child: Text('ChatGPT'),
),
PopupMenuItem<String>(
value: 'ErnieBot',
child: Text('文心一言'),
),
PopupMenuItem<String>(
value: 'QwenBot',
child: Text('通義千問'),
),
// 添加更多的 AI 類型
],
);
if (selectedValue != null) {
setState(() {
_appBarTitle = selectedValue == 'QwenBot' ? '通義千問' : selectedValue; // 更新標(biāo)題
_aiProvider = AIProvider(type: selectedValue); // 更新 AIProvider
});
}
}
//...
}
這樣寫方法中重復(fù)代碼太多了,我們可以使用 List.generate 來生成 PopupMenuButton 的子菜單項(xiàng)座哩,通過循環(huán)遍歷 aiTypes 列表徒扶,并使用每個(gè)元素創(chuàng)建一個(gè) PopupMenuItem。這樣就可以實(shí)現(xiàn)通過循環(huán)構(gòu)造 PopupMenuButton 的子菜單項(xiàng)根穷。
寫法 2
void _showPopupMenu(BuildContext context) {
showMenu(
context: context,
position: RelativeRect.fromLTRB(0, AppBar().preferredSize.height, 0, 0),
items: List.generate(aiTypes.length, (index) {
return PopupMenuItem<String>(
value: aiTypes[index],
child: Text(aiTitles[index]),
);
}),
elevation: 8.0,
).then((value) {
if (value != null) {
setState(() {
_appBarTitle = value == 'QwenBot' ? '通義千問' : value; // 更新標(biāo)題
_aiProvider = AIProvider(type: value); // 更新 AIProvider
});
}
});
}