gpt4all
792 строки · 30.2 Кб
1import QtCore
2import QtQuick
3import QtQuick.Controls
4import QtQuick.Controls.Basic
5import QtQuick.Layouts
6import modellist
7import mysettings
8
9MySettingsTab {
10onRestoreDefaultsClicked: {
11MySettings.restoreModelDefaults(root.currentModelInfo);
12}
13title: qsTr("Model/Character Settings")
14contentItem: GridLayout {
15id: root
16columns: 3
17rowSpacing: 10
18columnSpacing: 10
19
20property var currentModelName: comboBox.currentText
21property var currentModelId: comboBox.currentValue
22property var currentModelInfo: ModelList.modelInfo(root.currentModelId)
23
24MySettingsLabel {
25id: label
26Layout.row: 0
27Layout.column: 0
28text: qsTr("Model/Character")
29}
30
31RowLayout {
32Layout.fillWidth: true
33Layout.row: 1
34Layout.column: 0
35Layout.columnSpan: 2
36height: label.height + 20
37spacing: 10
38
39MyComboBox {
40id: comboBox
41Layout.fillWidth: true
42model: ModelList.installedModels
43valueRole: "id"
44textRole: "name"
45currentIndex: 0
46contentItem: Text {
47leftPadding: 10
48rightPadding: 20
49text: comboBox.currentText
50font: comboBox.font
51color: theme.textColor
52verticalAlignment: Text.AlignVCenter
53elide: Text.ElideRight
54}
55delegate: ItemDelegate {
56width: comboBox.width
57contentItem: Text {
58text: name
59color: theme.textColor
60font: comboBox.font
61elide: Text.ElideRight
62verticalAlignment: Text.AlignVCenter
63}
64background: Rectangle {
65color: highlighted ? theme.lightContrast : theme.darkContrast
66}
67highlighted: comboBox.highlightedIndex === index
68}
69}
70
71MySettingsButton {
72id: cloneButton
73text: qsTr("Clone")
74onClicked: {
75var id = ModelList.clone(root.currentModelInfo);
76comboBox.currentIndex = comboBox.indexOfValue(id);
77}
78}
79
80MySettingsDestructiveButton {
81id: removeButton
82enabled: root.currentModelInfo.isClone
83text: qsTr("Remove")
84onClicked: {
85ModelList.remove(root.currentModelInfo);
86comboBox.currentIndex = 0;
87}
88}
89}
90
91RowLayout {
92Layout.row: 2
93Layout.column: 0
94Layout.topMargin: 15
95spacing: 10
96MySettingsLabel {
97id: uniqueNameLabel
98text: qsTr("Unique Name")
99}
100MySettingsLabel {
101id: uniqueNameLabelHelp
102visible: false
103text: qsTr("Must contain a non-empty unique name that does not match any existing model/character.")
104color: theme.textErrorColor
105wrapMode: TextArea.Wrap
106}
107}
108
109MyTextField {
110id: uniqueNameField
111text: root.currentModelName
112font.pixelSize: theme.fontSizeLarge
113enabled: root.currentModelInfo.isClone || root.currentModelInfo.description === ""
114Layout.row: 3
115Layout.column: 0
116Layout.columnSpan: 2
117Layout.fillWidth: true
118Connections {
119target: MySettings
120function onNameChanged() {
121uniqueNameField.text = root.currentModelInfo.name;
122}
123}
124Connections {
125target: root
126function onCurrentModelInfoChanged() {
127uniqueNameField.text = root.currentModelInfo.name;
128}
129}
130onTextChanged: {
131if (text !== "" && ModelList.isUniqueName(text)) {
132MySettings.setModelName(root.currentModelInfo, text);
133}
134uniqueNameLabelHelp.visible = root.currentModelInfo.name !== "" &&
135(text === "" || (text !== root.currentModelInfo.name && !ModelList.isUniqueName(text)));
136}
137}
138
139MySettingsLabel {
140text: qsTr("Model File")
141Layout.row: 4
142Layout.column: 0
143Layout.topMargin: 15
144}
145
146MyTextField {
147text: root.currentModelInfo.filename
148font.pixelSize: theme.fontSizeLarge
149enabled: false
150Layout.row: 5
151Layout.column: 0
152Layout.columnSpan: 2
153Layout.fillWidth: true
154}
155
156MySettingsLabel {
157visible: !root.currentModelInfo.isOnline
158text: qsTr("System Prompt")
159Layout.row: 6
160Layout.column: 0
161Layout.topMargin: 15
162}
163
164Rectangle {
165id: systemPrompt
166visible: !root.currentModelInfo.isOnline
167Layout.row: 7
168Layout.column: 0
169Layout.columnSpan: 2
170Layout.fillWidth: true
171color: "transparent"
172Layout.minimumHeight: Math.max(100, systemPromptArea.contentHeight + 20)
173MyTextArea {
174id: systemPromptArea
175anchors.fill: parent
176text: root.currentModelInfo.systemPrompt
177Connections {
178target: MySettings
179function onSystemPromptChanged() {
180systemPromptArea.text = root.currentModelInfo.systemPrompt;
181}
182}
183Connections {
184target: root
185function onCurrentModelInfoChanged() {
186systemPromptArea.text = root.currentModelInfo.systemPrompt;
187}
188}
189onTextChanged: {
190MySettings.setModelSystemPrompt(root.currentModelInfo, text)
191}
192Accessible.role: Accessible.EditableText
193ToolTip.text: qsTr("The systemPrompt allows instructions to the model at the beginning of a chat.\nNOTE: A longer, detailed system prompt can lead to higher quality answers, but can also slow down generation.")
194ToolTip.visible: hovered
195ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
196}
197}
198
199RowLayout {
200Layout.row: 8
201Layout.column: 0
202Layout.columnSpan: 2
203Layout.topMargin: 15
204spacing: 10
205MySettingsLabel {
206id: promptTemplateLabel
207text: qsTr("Prompt Template")
208}
209MySettingsLabel {
210id: promptTemplateLabelHelp
211text: qsTr("Must contain the string \"%1\" to be replaced with the user's input.")
212color: theme.textErrorColor
213visible: templateTextArea.text.indexOf("%1") === -1
214wrapMode: TextArea.Wrap
215}
216}
217
218Rectangle {
219id: promptTemplate
220Layout.row: 9
221Layout.column: 0
222Layout.columnSpan: 2
223Layout.fillWidth: true
224Layout.minimumHeight: Math.max(100, templateTextArea.contentHeight + 20)
225color: "transparent"
226clip: true
227MyTextArea {
228id: templateTextArea
229anchors.fill: parent
230text: root.currentModelInfo.promptTemplate
231Connections {
232target: MySettings
233function onPromptTemplateChanged() {
234templateTextArea.text = root.currentModelInfo.promptTemplate;
235}
236}
237Connections {
238target: root
239function onCurrentModelInfoChanged() {
240templateTextArea.text = root.currentModelInfo.promptTemplate;
241}
242}
243onTextChanged: {
244if (templateTextArea.text.indexOf("%1") !== -1) {
245MySettings.setModelPromptTemplate(root.currentModelInfo, text)
246}
247}
248Accessible.role: Accessible.EditableText
249Accessible.name: promptTemplateLabel.text
250Accessible.description: promptTemplateLabelHelp.text
251ToolTip.text: qsTr("The prompt template partially determines how models will respond to prompts.\nNOTE: A longer, detailed template can lead to higher quality answers, but can also slow down generation.")
252ToolTip.visible: hovered
253ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
254}
255}
256
257Rectangle {
258id: optionalImageRect
259visible: false // FIXME: for later
260Layout.row: 2
261Layout.column: 1
262Layout.rowSpan: 5
263Layout.alignment: Qt.AlignHCenter
264Layout.fillHeight: true
265Layout.maximumWidth: height
266Layout.topMargin: 35
267Layout.bottomMargin: 35
268Layout.leftMargin: 35
269width: 3000
270radius: 10
271color: "transparent"
272Item {
273anchors.centerIn: parent
274height: childrenRect.height
275Image {
276id: img
277anchors.horizontalCenter: parent.horizontalCenter
278width: 100
279height: 100
280source: "qrc:/gpt4all/icons/image.svg"
281}
282Text {
283text: qsTr("Add\noptional image")
284font.pixelSize: theme.fontSizeLarge
285anchors.top: img.bottom
286anchors.horizontalCenter: parent.horizontalCenter
287wrapMode: TextArea.Wrap
288horizontalAlignment: Qt.AlignHCenter
289color: theme.mutedTextColor
290}
291}
292}
293
294MySettingsLabel {
295text: qsTr("Generation Settings")
296Layout.row: 10
297Layout.column: 0
298Layout.columnSpan: 2
299Layout.topMargin: 15
300Layout.alignment: Qt.AlignHCenter
301Layout.minimumWidth: promptTemplate.width
302horizontalAlignment: Qt.AlignHCenter
303font.pixelSize: theme.fontSizeLarge
304font.bold: true
305}
306
307GridLayout {
308Layout.row: 11
309Layout.column: 0
310Layout.columnSpan: 2
311Layout.topMargin: 15
312Layout.fillWidth: true
313Layout.minimumWidth: promptTemplate.width
314columns: 4
315rowSpacing: 10
316columnSpacing: 10
317
318MySettingsLabel {
319id: contextLengthLabel
320visible: !root.currentModelInfo.isOnline
321text: qsTr("Context Length")
322Layout.row: 0
323Layout.column: 0
324}
325MyTextField {
326id: contextLengthField
327visible: !root.currentModelInfo.isOnline
328text: root.currentModelInfo.contextLength
329font.pixelSize: theme.fontSizeLarge
330color: theme.textColor
331ToolTip.text: qsTr("Maximum combined prompt/response tokens before information is lost.\nUsing more context than the model was trained on will yield poor results.\nNOTE: Does not take effect until you reload the model.")
332ToolTip.visible: hovered
333Layout.row: 0
334Layout.column: 1
335Connections {
336target: MySettings
337function onContextLengthChanged() {
338contextLengthField.text = root.currentModelInfo.contextLength;
339}
340}
341Connections {
342target: root
343function onCurrentModelInfoChanged() {
344contextLengthField.text = root.currentModelInfo.contextLength;
345}
346}
347onEditingFinished: {
348var val = parseInt(text)
349if (isNaN(val)) {
350text = root.currentModelInfo.contextLength
351} else {
352if (val < 8) {
353val = 8
354contextLengthField.text = val
355} else if (val > root.currentModelInfo.maxContextLength) {
356val = root.currentModelInfo.maxContextLength
357contextLengthField.text = val
358}
359MySettings.setModelContextLength(root.currentModelInfo, val)
360focus = false
361}
362}
363Accessible.role: Accessible.EditableText
364Accessible.name: contextLengthLabel.text
365Accessible.description: ToolTip.text
366}
367
368MySettingsLabel {
369id: tempLabel
370text: qsTr("Temperature")
371Layout.row: 1
372Layout.column: 2
373}
374
375MyTextField {
376id: temperatureField
377text: root.currentModelInfo.temperature
378font.pixelSize: theme.fontSizeLarge
379color: theme.textColor
380ToolTip.text: qsTr("Temperature increases the chances of choosing less likely tokens.\nNOTE: Higher temperature gives more creative but less predictable outputs.")
381ToolTip.visible: hovered
382Layout.row: 1
383Layout.column: 3
384validator: DoubleValidator {
385locale: "C"
386}
387Connections {
388target: MySettings
389function onTemperatureChanged() {
390temperatureField.text = root.currentModelInfo.temperature;
391}
392}
393Connections {
394target: root
395function onCurrentModelInfoChanged() {
396temperatureField.text = root.currentModelInfo.temperature;
397}
398}
399onEditingFinished: {
400var val = parseFloat(text)
401if (!isNaN(val)) {
402MySettings.setModelTemperature(root.currentModelInfo, val)
403focus = false
404} else {
405text = root.currentModelInfo.temperature
406}
407}
408Accessible.role: Accessible.EditableText
409Accessible.name: tempLabel.text
410Accessible.description: ToolTip.text
411}
412MySettingsLabel {
413id: topPLabel
414text: qsTr("Top P")
415Layout.row: 2
416Layout.column: 0
417}
418MyTextField {
419id: topPField
420text: root.currentModelInfo.topP
421color: theme.textColor
422font.pixelSize: theme.fontSizeLarge
423ToolTip.text: qsTr("Only the most likely tokens up to a total probability of top_p can be chosen.\nNOTE: Prevents choosing highly unlikely tokens, aka Nucleus Sampling")
424ToolTip.visible: hovered
425Layout.row: 2
426Layout.column: 1
427validator: DoubleValidator {
428locale: "C"
429}
430Connections {
431target: MySettings
432function onTopPChanged() {
433topPField.text = root.currentModelInfo.topP;
434}
435}
436Connections {
437target: root
438function onCurrentModelInfoChanged() {
439topPField.text = root.currentModelInfo.topP;
440}
441}
442onEditingFinished: {
443var val = parseFloat(text)
444if (!isNaN(val)) {
445MySettings.setModelTopP(root.currentModelInfo, val)
446focus = false
447} else {
448text = root.currentModelInfo.topP
449}
450}
451Accessible.role: Accessible.EditableText
452Accessible.name: topPLabel.text
453Accessible.description: ToolTip.text
454}
455MySettingsLabel {
456id: minPLabel
457text: qsTr("Min P")
458Layout.row: 3
459Layout.column: 0
460}
461MyTextField {
462id: minPField
463text: root.currentModelInfo.minP
464color: theme.textColor
465font.pixelSize: theme.fontSizeLarge
466ToolTip.text: qsTr("Sets the minimum relative probability for a token to be considered.")
467ToolTip.visible: hovered
468Layout.row: 3
469Layout.column: 1
470validator: DoubleValidator {
471locale: "C"
472}
473Connections {
474target: MySettings
475function onMinPChanged() {
476minPField.text = root.currentModelInfo.minP;
477}
478}
479Connections {
480target: root
481function onCurrentModelInfoChanged() {
482minPField.text = root.currentModelInfo.minP;
483}
484}
485onEditingFinished: {
486var val = parseFloat(text)
487if (!isNaN(val)) {
488MySettings.setModelMinP(root.currentModelInfo, val)
489focus = false
490} else {
491text = root.currentModelInfo.minP
492}
493}
494Accessible.role: Accessible.EditableText
495Accessible.name: minPLabel.text
496Accessible.description: ToolTip.text
497}
498
499MySettingsLabel {
500id: topKLabel
501visible: !root.currentModelInfo.isOnline
502text: qsTr("Top K")
503Layout.row: 2
504Layout.column: 2
505}
506MyTextField {
507id: topKField
508visible: !root.currentModelInfo.isOnline
509text: root.currentModelInfo.topK
510color: theme.textColor
511font.pixelSize: theme.fontSizeLarge
512ToolTip.text: qsTr("Only the top K most likely tokens will be chosen from")
513ToolTip.visible: hovered
514Layout.row: 2
515Layout.column: 3
516validator: IntValidator {
517bottom: 1
518}
519Connections {
520target: MySettings
521function onTopKChanged() {
522topKField.text = root.currentModelInfo.topK;
523}
524}
525Connections {
526target: root
527function onCurrentModelInfoChanged() {
528topKField.text = root.currentModelInfo.topK;
529}
530}
531onEditingFinished: {
532var val = parseInt(text)
533if (!isNaN(val)) {
534MySettings.setModelTopK(root.currentModelInfo, val)
535focus = false
536} else {
537text = root.currentModelInfo.topK
538}
539}
540Accessible.role: Accessible.EditableText
541Accessible.name: topKLabel.text
542Accessible.description: ToolTip.text
543}
544MySettingsLabel {
545id: maxLengthLabel
546visible: !root.currentModelInfo.isOnline
547text: qsTr("Max Length")
548Layout.row: 0
549Layout.column: 2
550}
551MyTextField {
552id: maxLengthField
553visible: !root.currentModelInfo.isOnline
554text: root.currentModelInfo.maxLength
555color: theme.textColor
556font.pixelSize: theme.fontSizeLarge
557ToolTip.text: qsTr("Maximum length of response in tokens")
558ToolTip.visible: hovered
559Layout.row: 0
560Layout.column: 3
561validator: IntValidator {
562bottom: 1
563}
564Connections {
565target: MySettings
566function onMaxLengthChanged() {
567maxLengthField.text = root.currentModelInfo.maxLength;
568}
569}
570Connections {
571target: root
572function onCurrentModelInfoChanged() {
573maxLengthField.text = root.currentModelInfo.maxLength;
574}
575}
576onEditingFinished: {
577var val = parseInt(text)
578if (!isNaN(val)) {
579MySettings.setModelMaxLength(root.currentModelInfo, val)
580focus = false
581} else {
582text = root.currentModelInfo.maxLength
583}
584}
585Accessible.role: Accessible.EditableText
586Accessible.name: maxLengthLabel.text
587Accessible.description: ToolTip.text
588}
589
590MySettingsLabel {
591id: batchSizeLabel
592visible: !root.currentModelInfo.isOnline
593text: qsTr("Prompt Batch Size")
594Layout.row: 1
595Layout.column: 0
596}
597MyTextField {
598id: batchSizeField
599visible: !root.currentModelInfo.isOnline
600text: root.currentModelInfo.promptBatchSize
601color: theme.textColor
602font.pixelSize: theme.fontSizeLarge
603ToolTip.text: qsTr("Amount of prompt tokens to process at once.\nNOTE: Higher values can speed up reading prompts but will use more RAM")
604ToolTip.visible: hovered
605Layout.row: 1
606Layout.column: 1
607validator: IntValidator {
608bottom: 1
609}
610Connections {
611target: MySettings
612function onPromptBatchSizeChanged() {
613batchSizeField.text = root.currentModelInfo.promptBatchSize;
614}
615}
616Connections {
617target: root
618function onCurrentModelInfoChanged() {
619batchSizeField.text = root.currentModelInfo.promptBatchSize;
620}
621}
622onEditingFinished: {
623var val = parseInt(text)
624if (!isNaN(val)) {
625MySettings.setModelPromptBatchSize(root.currentModelInfo, val)
626focus = false
627} else {
628text = root.currentModelInfo.promptBatchSize
629}
630}
631Accessible.role: Accessible.EditableText
632Accessible.name: batchSizeLabel.text
633Accessible.description: ToolTip.text
634}
635MySettingsLabel {
636id: repeatPenaltyLabel
637visible: !root.currentModelInfo.isOnline
638text: qsTr("Repeat Penalty")
639Layout.row: 4
640Layout.column: 2
641}
642MyTextField {
643id: repeatPenaltyField
644visible: !root.currentModelInfo.isOnline
645text: root.currentModelInfo.repeatPenalty
646color: theme.textColor
647font.pixelSize: theme.fontSizeLarge
648ToolTip.text: qsTr("Amount to penalize repetitiveness of the output")
649ToolTip.visible: hovered
650Layout.row: 4
651Layout.column: 3
652validator: DoubleValidator {
653locale: "C"
654}
655Connections {
656target: MySettings
657function onRepeatPenaltyChanged() {
658repeatPenaltyField.text = root.currentModelInfo.repeatPenalty;
659}
660}
661Connections {
662target: root
663function onCurrentModelInfoChanged() {
664repeatPenaltyField.text = root.currentModelInfo.repeatPenalty;
665}
666}
667onEditingFinished: {
668var val = parseFloat(text)
669if (!isNaN(val)) {
670MySettings.setModelRepeatPenalty(root.currentModelInfo, val)
671focus = false
672} else {
673text = root.currentModelInfo.repeatPenalty
674}
675}
676Accessible.role: Accessible.EditableText
677Accessible.name: repeatPenaltyLabel.text
678Accessible.description: ToolTip.text
679}
680MySettingsLabel {
681id: repeatPenaltyTokensLabel
682visible: !root.currentModelInfo.isOnline
683text: qsTr("Repeat Penalty Tokens")
684Layout.row: 3
685Layout.column: 2
686}
687MyTextField {
688id: repeatPenaltyTokenField
689visible: !root.currentModelInfo.isOnline
690text: root.currentModelInfo.repeatPenaltyTokens
691color: theme.textColor
692font.pixelSize: theme.fontSizeLarge
693ToolTip.text: qsTr("How far back in output to apply repeat penalty")
694ToolTip.visible: hovered
695Layout.row: 3
696Layout.column: 3
697validator: IntValidator {
698bottom: 1
699}
700Connections {
701target: MySettings
702function onRepeatPenaltyTokensChanged() {
703repeatPenaltyTokenField.text = root.currentModelInfo.repeatPenaltyTokens;
704}
705}
706Connections {
707target: root
708function onCurrentModelInfoChanged() {
709repeatPenaltyTokenField.text = root.currentModelInfo.repeatPenaltyTokens;
710}
711}
712onEditingFinished: {
713var val = parseInt(text)
714if (!isNaN(val)) {
715MySettings.setModelRepeatPenaltyTokens(root.currentModelInfo, val)
716focus = false
717} else {
718text = root.currentModelInfo.repeatPenaltyTokens
719}
720}
721Accessible.role: Accessible.EditableText
722Accessible.name: repeatPenaltyTokensLabel.text
723Accessible.description: ToolTip.text
724}
725
726MySettingsLabel {
727id: gpuLayersLabel
728visible: !root.currentModelInfo.isOnline
729text: qsTr("GPU Layers")
730Layout.row: 4
731Layout.column: 0
732}
733MyTextField {
734id: gpuLayersField
735visible: !root.currentModelInfo.isOnline
736text: root.currentModelInfo.gpuLayers
737font.pixelSize: theme.fontSizeLarge
738color: theme.textColor
739ToolTip.text: qsTr("How many GPU layers to load into VRAM. Decrease this if GPT4All runs out of VRAM while loading this model.\nLower values increase CPU load and RAM usage, and make inference slower.\nNOTE: Does not take effect until you reload the model.")
740ToolTip.visible: hovered
741Layout.row: 4
742Layout.column: 1
743Connections {
744target: MySettings
745function onGpuLayersChanged() {
746gpuLayersField.text = root.currentModelInfo.gpuLayers
747}
748}
749Connections {
750target: root
751function onCurrentModelInfoChanged() {
752if (root.currentModelInfo.gpuLayers === 100) {
753gpuLayersField.text = root.currentModelInfo.maxGpuLayers
754} else {
755gpuLayersField.text = root.currentModelInfo.gpuLayers
756}
757}
758}
759onEditingFinished: {
760var val = parseInt(text)
761if (isNaN(val)) {
762gpuLayersField.text = root.currentModelInfo.gpuLayers
763} else {
764if (val < 1) {
765val = 1
766gpuLayersField.text = val
767} else if (val > root.currentModelInfo.maxGpuLayers) {
768val = root.currentModelInfo.maxGpuLayers
769gpuLayersField.text = val
770}
771MySettings.setModelGpuLayers(root.currentModelInfo, val)
772focus = false
773}
774}
775Accessible.role: Accessible.EditableText
776Accessible.name: gpuLayersLabel.text
777Accessible.description: ToolTip.text
778}
779}
780
781Rectangle {
782Layout.row: 12
783Layout.column: 0
784Layout.columnSpan: 2
785Layout.topMargin: 15
786Layout.fillWidth: true
787Layout.minimumWidth: promptTemplate.width
788height: 3
789color: theme.accentColor
790}
791}
792}
793