Skip to content

Commit

Permalink
Allow custom model list
Browse files Browse the repository at this point in the history
  • Loading branch information
onlyGuo committed Nov 3, 2024
1 parent 2e430a5 commit e22e8e0
Show file tree
Hide file tree
Showing 10 changed files with 452 additions and 117 deletions.
4 changes: 2 additions & 2 deletions lib/components/Chat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class Chat extends StatelessWidget {
}
}

Util.askGPT(settingController.setting.value.apiSetting.baseUrl,
Util.askGPT(settingController.setting.value.apiSetting.isCustom ? settingController.setting.value.apiSetting.baseUrl : 'https://api.openai.com',
model, controller.currentChat.value.temperature,
settingController.setting.value.apiSetting.accessToken, plugins, reqMsg, (result, finish) {
controller.currentChat.update((val) {
Expand Down Expand Up @@ -172,4 +172,4 @@ class Chat extends StatelessWidget {
}


}
}
60 changes: 60 additions & 0 deletions lib/components/ModelController.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import 'dart:convert';

import 'package:chatgpt_desktop/entity/Model.dart';
import 'package:chatgpt_desktop/utils/Util.dart';
import 'package:get/get.dart';

class ModelController extends GetxController{

RxList<Model> items = RxList<Model>([]);
Rx<Model> selectModel = Model(displayName: 'GPT-3.5', name: 'gpt-3.5-turbo').obs;

void addModel(displayName, name) => {
items.add(Model(displayName: displayName, name: name)),
Util.writeFile('models.json', jsonEncode(items)),
update()
};

void removeModel(Model model) => {
items.remove(model),
Util.writeFile('models.json', jsonEncode(items)),
update()
};

@override
void onReady() {
// 从本地存储中获取
try {
Util.readFile('models.json').then((value) {
if(value.isEmpty){
value = jsonEncode([
Model(displayName: 'GPT-3.5', name: 'gpt-3.5-turbo'),
Model(displayName: 'GPT-4', name: 'gpt-4-turbo'),
]);
Util.writeFile('models.json', value);
}
jsonDecode(value).map<Model>((item) => Model.fromJson(item)).toList().forEach((element) {
items.add(element);
});
selectModel.value = items[0];
update(); // 通知 Flutter 刷新 UI
});
} catch (e) {
items.add(Model(displayName: 'GPT-3.5', name: 'gpt-3.5-turbo'),);
items.add(Model(displayName: 'GPT-4', name: 'gpt-4-turbo'),);
selectModel.value = items[0];
Util.writeFile('models.json', jsonEncode(items));
}
super.onReady();
}


void updateChatName(int index, String displayName, String name){
items[index].displayName = displayName;
items[index].name = name;
items.refresh();
Util.writeFile('models.json', jsonEncode(items));
update();
}
}

115 changes: 29 additions & 86 deletions lib/components/chat/ChatInput.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import 'dart:io';

import 'package:bitmap/bitmap.dart';
import 'package:chatgpt_desktop/enums/ModelEnums.dart';
import 'package:chatgpt_desktop/components/ModelController.dart';
import 'package:chatgpt_desktop/entity/Model.dart';
import 'package:chatgpt_desktop/native_interface/NativeScreenshot.dart';
import 'package:chatgpt_desktop/native_interface/WXDLL.dart';
import 'package:chatgpt_desktop/utils/Util.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:screen_capturer/screen_capturer.dart';
// import 'package:chatgpt_desktop/utils/MyScreen_captuer.dart';

class ChatInput extends StatelessWidget{
InputFinish? onFinish;
Expand All @@ -18,10 +14,11 @@ class ChatInput extends StatelessWidget{
TextEditingController controller = TextEditingController();
FocusNode focusNode = FocusNode();


var selectModel = ModelEnums.models.first.obs;
ModelController modelController = Get.put(ModelController());
var selectedImage = ''.obs;



@override
Widget build(BuildContext context) {
// controller.addListener(() {
Expand All @@ -32,7 +29,7 @@ class ChatInput extends StatelessWidget{
// controller.clear();
// }
// });

return Container(
color: const Color.fromARGB(255, 252, 252, 252),
height: 180,
Expand Down Expand Up @@ -94,8 +91,8 @@ class ChatInput extends StatelessWidget{
}, icon: Icon(Icons.cut), tooltip: 'Cut'),
Expanded(child: Container()),
Obx(() => DropdownButton<Model>(
value: selectModel.value,
items: ModelEnums.models
value: modelController.selectModel.value,
items: modelController.items
.map((Model value) {
return DropdownMenuItem<Model>(
value: value,
Expand All @@ -104,7 +101,8 @@ class ChatInput extends StatelessWidget{
}).toList(),
underline: Container(),
onChanged: (newValue) {
selectModel.value = newValue!;
modelController.selectModel.value = newValue!;
modelController.update();
},
)),

Expand All @@ -119,47 +117,26 @@ class ChatInput extends StatelessWidget{
),
),
Expanded(
child: Column(
children: [
Obx(() => selectedImage.value.isEmpty ? Container() : Container(
height: 50,
padding: const EdgeInsets.only(left: 5, right: 5),
// color: Colors.red,
child: Row(
children: [
showSelectedImage(),
],
)
)),
Expanded(
child: ListView(
children: [
Container(
// padding: const EdgeInsets.all(5),
// color: Colors.red,
child: RawKeyboardListener(
focusNode: focusNode,
onKey: handleKeyPress,
child: TextField(
decoration: const InputDecoration(
hintText: 'Type a message, press Enter to send, press Shift+Enter to newline.',
border: OutlineInputBorder(
borderSide: BorderSide.none,
),
),
style: const TextStyle(
fontSize: 12,
),
maxLines: null,
minLines: 1,
controller: controller,
),
),
)
],
child: Container(
// padding: const EdgeInsets.all(5),
// color: Colors.red,
child: RawKeyboardListener(
focusNode: focusNode,
onKey: handleKeyPress,
child: TextField(
decoration: const InputDecoration(
hintText: 'Type a message, press Enter to send, press Shift+Enter to newline.',
border: OutlineInputBorder(
borderSide: BorderSide.none,
),
),
style: const TextStyle(
fontSize: 12,
),
maxLines: 5,
controller: controller,
),
]
),
),
)
],
Expand All @@ -184,45 +161,11 @@ class ChatInput extends StatelessWidget{
String text = controller.text;
controller.clear();
if (onFinish != null) {
onFinish!(text, selectModel.value.name);
onFinish!(text, modelController.selectModel.value.name);
}
}
}
}

Widget showSelectedImage(){
return Container(
height: 50,
padding: const EdgeInsets.all(3),
// 边框圆角,超出部分隐藏
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.white,
border: Border.all(color: Colors.grey.withOpacity(0.5)),
),
child: Row(
// 显示图片和删除按钮,图片cover显示
children: [
Image.file(File(selectedImage.value), width: 44, height: 44, fit: BoxFit.cover,),
const SizedBox(width: 5,),
// 按钮小一些
SizedBox(
height: 18,
width: 18,
child: IconButton(
onPressed: (){
selectedImage.value = '';
},
padding: EdgeInsets.zero,
icon: Icon(Icons.close),
iconSize: 12,
tooltip: "Delete the image",
),
),
],
),
);
}
}

typedef InputFinish = void Function(String message, String model);
2 changes: 1 addition & 1 deletion lib/components/chat/message/ChatMessageWidget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,4 @@ class ChatMessageWidget extends StatelessWidget {
// ),
// );
// }
}
}
21 changes: 21 additions & 0 deletions lib/entity/Model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class Model {

String displayName;
String name;

Model({
required this.name,
required this.displayName,
});

// toJson
Map<String, dynamic> toJson() => {
'name': name,
'displayName': displayName,
};

// fromJson
Model.fromJson(Map<String, dynamic> json)
: name = json['name'],
displayName = json['displayName'];
}
17 changes: 0 additions & 17 deletions lib/enums/ModelEnums.dart

This file was deleted.

14 changes: 13 additions & 1 deletion lib/utils/Util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,18 @@ class Util{
if(tools.isNotEmpty){
requestBody["tools"] = tools;
}
if(basicUrl.isEmpty){
callback("BasicUrl is empty, please jump to the API Setting page to make the settings.", true);
return;
}
if(accessKey.isEmpty){
callback("AccessKey is empty, please jump to the API Setting page to make the settings.", true);
return;
}
if(model.isEmpty){
callback("Model is empty, please select model.", true);
return;
}
basicUrl = basicUrl.endsWith('/') ? basicUrl : '$basicUrl/';
var request = http.Request("POST", Uri.parse('${basicUrl}v1/chat/completions'));
request.headers["Authorization"] = "Bearer $accessKey";
Expand Down Expand Up @@ -297,4 +309,4 @@ class Util{
});
}
}
typedef GPTCallbackFunction = void Function(String result, bool finish);
typedef GPTCallbackFunction = void Function(String result, bool finish);
Loading

0 comments on commit e22e8e0

Please sign in to comment.