odant-work 1.0.16 → 1.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/#system/package-manifest.json +16 -16
- package/$server/$folder/handlers/pages/form/$handler/form.js +2 -1
- package/MODELS/$ai/$folder/$class/$ai/class.js +1 -1
- package/MODELS/$ai/$folder/$class/$ai/handlers/pages/form/trainer/$handler/class.js +6 -4
- package/MODELS/$ai/$folder/$class/$ai/handlers/pages/form/trainer/$handler/trainer.js +344 -3
- package/MODELS/$ai/$folder/$class/$provider/handlers/pages/form/provider/$handler/class.js +3 -3
- package/MODELS/$ai/$folder/$class/$provider/handlers/pages/form/trainer/$handler/class.js +3 -3
- package/MODELS/$ai/$folder/$class/$provider/handlers/pages/form/trainer/$handler/trainer.js +530 -920
- package/package.json +1 -1
- package/sources/data/progress.md +10 -0
- package/sources/modules/trainer/index.js +41 -1
- package/sources/modules/trainer/local-engine.js +67 -1
- package/sources/modules/trainer/runner.js +47 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"packageName": "odant-work",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"createdAt":
|
|
5
|
-
"updatedAt":
|
|
3
|
+
"version": "1.0.17",
|
|
4
|
+
"createdAt": 1794561330772,
|
|
5
|
+
"updatedAt": 1794561330772,
|
|
6
6
|
"files": {
|
|
7
7
|
"run.mjs": "f8918c612e8641e9beee06221be6680aa6fd21f25468451f2ac857fd51772266",
|
|
8
|
-
"package.json": "
|
|
9
|
-
"package-lock.json": "
|
|
8
|
+
"package.json": "f8c5cd13f6ca29599af16859f46d250ffe1c1f8326b8e8078aa7ed0897671670",
|
|
9
|
+
"package-lock.json": "147f2c1fef927e961c043fc228f5c852e14076ad7fef428d65fe61681d9ec3f4",
|
|
10
10
|
"sources/client/class.js": "c3fb8f143fc83aaa2df1ddeddd412d2d4dfe88656578095babe2df34fb3b3922",
|
|
11
11
|
"sources/client/field.js": "ffdd50fa8b6ec515cc42da5fca96658ff2b20e274601a1f926e0031372467a19",
|
|
12
12
|
"sources/client/file.js": "667101d75fa30840370d5be232e518aaac7c1fd52ca05a12da560eef6c0848b0",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"sources/data/objects.js": "23f51d5b00cd766fe27879b874738bc9bd9056bd6e27285fb7a52926c0dbc6a8",
|
|
27
27
|
"sources/data/posting.js": "6595bb9ec632539ae7629504db327d25a491e61c1cdc598bb43d08ea0d45548d",
|
|
28
28
|
"sources/data/print.js": "704f0f2fc80c6466a4196e4650d763150cf9b592eab14ea67ece85d51100107c",
|
|
29
|
-
"sources/data/progress.md": "
|
|
29
|
+
"sources/data/progress.md": "0e443152a9b6647c9f845d2434be7567232bcf2c025fb416ba21b23867529a98",
|
|
30
30
|
"sources/data/readme.md": "593fa2ae07aa91bc26d7542275da6953a9cd419240a9a49e00cb62fb9d5d8e36",
|
|
31
31
|
"sources/data/reports.js": "0330f404860fe2589a7d46a2f0fe690ca23249bd841a062a26718742d4fd11d6",
|
|
32
32
|
"sources/data/schema.js": "2a598b33c9352e3b673639dda302caeb13620cf978960cbcaee906f7bb852d50",
|
|
@@ -167,10 +167,10 @@
|
|
|
167
167
|
"sources/modules/trainer/dataset.js": "ca91f11249ccf4fce9c15dc780711fa33059a3e1efbaf0ccdbbd59e529b0108e",
|
|
168
168
|
"sources/modules/trainer/halogen.js": "c3f51d41d86331b83b888e807fb0db973f116fc4e8d7f81f4b1ea7aaa1100129",
|
|
169
169
|
"sources/modules/trainer/huggingface.js": "f6db6b1ea97969360005cdfc9ae485c1dc519af28d175d0df1a486959408bc3a",
|
|
170
|
-
"sources/modules/trainer/index.js": "
|
|
171
|
-
"sources/modules/trainer/local-engine.js": "
|
|
170
|
+
"sources/modules/trainer/index.js": "715ec739676d2e4cd8cec2768ede93e2546c502b8452f1314fe676592594431a",
|
|
171
|
+
"sources/modules/trainer/local-engine.js": "83cd121b208248606c8cbfdb7100c5ab1b2f06dc56b5266d2df8feda0237be4d",
|
|
172
172
|
"sources/modules/trainer/providers.js": "18e075140bb14a9dd2ef70412942a03558d415abab9387d1d42c39f8c422b073",
|
|
173
|
-
"sources/modules/trainer/runner.js": "
|
|
173
|
+
"sources/modules/trainer/runner.js": "a438e38614a73834cbb9e542357b9cb76df3c16c2dd0b972c4be88383e3569a9",
|
|
174
174
|
"sources/modules/trainer/worker/local_infer_worker.py": "7b001d75c64ac3ae6de650f6d738f22bfc21b6bd0694b57248e5b40966deb443",
|
|
175
175
|
"sources/modules/trainer/worker/unsloth_train.py": "7774d94ffa6f60eed20c57a8dfdc12621d5d9f74d594c605dff32ff70e321e33",
|
|
176
176
|
"sources/modules/user-profile/user-profile.js": "47b71574ec51e6d40e218e996c8397b25f36418f21e69668c75f1df7d64eb914",
|
|
@@ -748,7 +748,7 @@
|
|
|
748
748
|
"$server/$folder/handlers/methods/help/$handler/class.js": "ff54bf976cbdc846d7c1b46ff12b111e99a3f4831240a4e420b73c98c0355a5c",
|
|
749
749
|
"$server/$folder/handlers/methods/info/$handler/class.js": "8752efb28abdcfad4e8ce56cfebcd8bb09ec0735cba7b84156d248bfcb0f9db0",
|
|
750
750
|
"$server/$folder/handlers/pages/form/$handler/class.js": "3902d3e1a8742afa2625410f97c68a3afac2559bd3d8f37044338edf7386d4df",
|
|
751
|
-
"$server/$folder/handlers/pages/form/$handler/form.js": "
|
|
751
|
+
"$server/$folder/handlers/pages/form/$handler/form.js": "559e4ccf8951105bdf80ce78897949a4eca8bd0a3e51fccefbcd4c42e8d4db24",
|
|
752
752
|
"$server/$folder/handlers/readme.md": "1167594c32f46323d229098a72e80a9865005c347373fdacef5af69838a0f8eb",
|
|
753
753
|
"$server/$folder/lib/calendar-form/calendar-form.js": "3035cab0a489c891d7dd7ed52ae5c475068b97361a1f7c855d500a0823614d1c",
|
|
754
754
|
"$server/$folder/lib/chat-item/chat-item.js": "f5d99b38eb4e00a46c656a1df98d0c3a2ed23e3b0143853bffbe7b9f03c24a01",
|
|
@@ -953,15 +953,15 @@
|
|
|
953
953
|
"MODULES/Register/STRUCTS/Банковский счёт/$struct/class.js": "166ffafd1c7d1609b174ae7766e77842e6294c6902baabe787225a2eeb026cce",
|
|
954
954
|
"MODULES/Register/STRUCTS/Единица измерения/$struct/class.js": "dd0982281ed782d23afd80d5985b79aa65c6acbe58dc080f943840ea798000b0",
|
|
955
955
|
"MODULES/Register/STRUCTS/Паспорт/$struct/class.js": "4a50808e4db7741b0384a775177545d71686a680ccda7ef0ec68bf81f9c988b5",
|
|
956
|
-
"MODELS/$ai/$folder/$class/$ai/class.js": "
|
|
957
|
-
"MODELS/$ai/$folder/$class/$ai/handlers/pages/form/trainer/$handler/class.js": "
|
|
958
|
-
"MODELS/$ai/$folder/$class/$ai/handlers/pages/form/trainer/$handler/trainer.js": "
|
|
956
|
+
"MODELS/$ai/$folder/$class/$ai/class.js": "7c18eef4b4ca0fbe195a238a91008755c10dd5ffbc6fb62e18c28a5232b7bf53",
|
|
957
|
+
"MODELS/$ai/$folder/$class/$ai/handlers/pages/form/trainer/$handler/class.js": "fe5ba834156495c28a34acd4b70a6b6b3bdfccb67ec7bf99e92a292afbb66d19",
|
|
958
|
+
"MODELS/$ai/$folder/$class/$ai/handlers/pages/form/trainer/$handler/trainer.js": "4c8098b3d0138b2c0d3b1e4f9039116371ed0893acbb2d36798856bc92f19ad0",
|
|
959
959
|
"MODELS/$ai/$folder/$class/$ai/methods/chat/$method/class.js": "a5859e701c8ea25c627247e6e6ae5d32115ba2f027a5fedea62ed1c7df0110ac",
|
|
960
960
|
"MODELS/$ai/$folder/$class/$provider/class.js": "069073501b93a95bb9d77e59ce71e53c7a8bcab2564c391b551f68a2453ac486",
|
|
961
|
-
"MODELS/$ai/$folder/$class/$provider/handlers/pages/form/provider/$handler/class.js": "
|
|
961
|
+
"MODELS/$ai/$folder/$class/$provider/handlers/pages/form/provider/$handler/class.js": "8d327820cefd696d351ac4fa7998994039e4d57ef7a9f8ae297209e4dd1b0a9e",
|
|
962
962
|
"MODELS/$ai/$folder/$class/$provider/handlers/pages/form/provider/$handler/provider.js": "b9ddf0040a9cd12e0dacd2dd3a61a1f0e62686cc664d02ef446326bc3991f4ce",
|
|
963
|
-
"MODELS/$ai/$folder/$class/$provider/handlers/pages/form/trainer/$handler/class.js": "
|
|
964
|
-
"MODELS/$ai/$folder/$class/$provider/handlers/pages/form/trainer/$handler/trainer.js": "
|
|
963
|
+
"MODELS/$ai/$folder/$class/$provider/handlers/pages/form/trainer/$handler/class.js": "06b279a1c053deb37dd7401c84df7f9370309b8dfbd35b368ab1bab4f635cb3f",
|
|
964
|
+
"MODELS/$ai/$folder/$class/$provider/handlers/pages/form/trainer/$handler/trainer.js": "9ee518c122246ca0d2820e0177b973e535c840ed900661eb25d0f56690bf42ca",
|
|
965
965
|
"MODELS/$ai/$folder/$class/$provider/readme.md": "d6ceef2010231ab121510c3d3f35630dd7009a069c7723f6673a0e264799b227",
|
|
966
966
|
"MODELS/$ai/class.js": "54e1bbbde88f8b1f272ff7f5cad87243407591748a44719b7ec90ae2b4962de7",
|
|
967
967
|
"MODELS/$ai/readme.md": "90d70305a2c85312282cf67cc468a0f0b417495cb3d5b3d2ca60c6f44b81cb77",
|
|
@@ -614,7 +614,8 @@ ODA({is: 'work-form',
|
|
|
614
614
|
staff: 'Поясни текущие назначения руководителя (BOSS), структуру рабочих мест (ROLES), использование USERS/GUESTS и привязанные ссылки LINKS.',
|
|
615
615
|
builder: 'Поясни схему полей (METADATA.FIELDS / STATIC / ANALYTICS / OVERLAY) и трёхосевое наследование класса.',
|
|
616
616
|
database: 'Поясни состав таблиц изолированной SQLite-базы данных и назначение текущей таблицы.',
|
|
617
|
-
trainer: 'Поясни
|
|
617
|
+
trainer: 'Поясни доступные модели ИИ, режим работы встроенного сервера ИИ, установку моделей в 1 клик и шаги дообучения.',
|
|
618
|
+
provider: 'Поясни настройку API-ключа провайдера ИИ в #secret, проверку связи и подключение моделей в 1 клик.',
|
|
618
619
|
mcp: 'Поясни подключённые MCP-серверы в /SERVICES, способы добавления новых MCP (через стандартный JSON mcpServers или пресеты) и работу с внешними навыками SKILL.md (включая @grill-me).',
|
|
619
620
|
};
|
|
620
621
|
const tailHint = viewHints[viewId] || 'Расскажи, что здесь отображается, какие данные сейчас представлены и какие действия доступны.';
|
|
@@ -22,7 +22,7 @@ const REMOTE_BODY_MAX = 32 * 1024 * 1024; // R7 (8.35): бинарный отв
|
|
|
22
22
|
|
|
23
23
|
export default {
|
|
24
24
|
icon: 'carbon:machine-learning-model',
|
|
25
|
-
form: '
|
|
25
|
+
form: 'trainer',
|
|
26
26
|
/** карточка модели для клиента: попадает в info, читается баром и usage-панелью */
|
|
27
27
|
$public: {
|
|
28
28
|
maxTokens: 4096, // лимит контекста (usage / info)
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
/** Мета хендлера form/trainer
|
|
1
|
+
/** Мета хендлера form/trainer (Модели ИИ — карточка модели $ai). */
|
|
2
2
|
export default {
|
|
3
|
-
icon: 'carbon:
|
|
4
|
-
label: '
|
|
3
|
+
icon: 'carbon:chip',
|
|
4
|
+
label: 'Модели ИИ',
|
|
5
5
|
roles: ['BOSS'],
|
|
6
6
|
order: 1,
|
|
7
7
|
allowUse($context) {
|
|
8
8
|
const p = String($context?.path || $context?.short || '');
|
|
9
|
-
|
|
9
|
+
if (!p || p === '/MODELS')
|
|
10
|
+
return false;
|
|
11
|
+
return $context?.type === '$ai';
|
|
10
12
|
},
|
|
11
13
|
}
|
|
@@ -1,6 +1,347 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* form/trainer для
|
|
2
|
+
* form/trainer для конкретного узла модели $ai — чистая карточка параметров, состояния и проверки модели.
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
export default {
|
|
5
|
+
imports: 'oda//icon',
|
|
6
|
+
template: /*html*/`
|
|
7
|
+
<style>
|
|
8
|
+
:host {
|
|
9
|
+
@apply --vertical;
|
|
10
|
+
@apply --flex;
|
|
11
|
+
overflow-y: auto;
|
|
12
|
+
background: var(--content-background, #ffffff);
|
|
13
|
+
color: var(--content-color, #1e293b);
|
|
14
|
+
font-size: 13px;
|
|
15
|
+
padding: 16px 20px;
|
|
16
|
+
gap: 14px;
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
}
|
|
19
|
+
.header-card {
|
|
20
|
+
@apply --horizontal;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: space-between;
|
|
23
|
+
gap: 12px;
|
|
24
|
+
padding: 12px 16px;
|
|
25
|
+
border-radius: 8px;
|
|
26
|
+
border: 1px solid var(--border-color, #cbd5e1);
|
|
27
|
+
background: var(--subtle-background, #f8fafc);
|
|
28
|
+
flex-wrap: wrap;
|
|
29
|
+
}
|
|
30
|
+
.header-left {
|
|
31
|
+
@apply --horizontal;
|
|
32
|
+
align-items: center;
|
|
33
|
+
gap: 12px;
|
|
34
|
+
min-width: 0;
|
|
35
|
+
}
|
|
36
|
+
.title {
|
|
37
|
+
font-size: 16px;
|
|
38
|
+
font-weight: 700;
|
|
39
|
+
}
|
|
40
|
+
.subtitle {
|
|
41
|
+
font-size: 12px;
|
|
42
|
+
opacity: 0.75;
|
|
43
|
+
margin-top: 2px;
|
|
44
|
+
}
|
|
45
|
+
.toolbar {
|
|
46
|
+
@apply --horizontal;
|
|
47
|
+
gap: 8px;
|
|
48
|
+
align-items: center;
|
|
49
|
+
flex-wrap: wrap;
|
|
50
|
+
}
|
|
51
|
+
.badge {
|
|
52
|
+
display: inline-flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
gap: 6px;
|
|
55
|
+
padding: 3px 10px;
|
|
56
|
+
border-radius: 999px;
|
|
57
|
+
font-size: 12px;
|
|
58
|
+
font-weight: 600;
|
|
59
|
+
}
|
|
60
|
+
.badge.active {
|
|
61
|
+
background: light-dark(#dcfce7, #14532d);
|
|
62
|
+
color: light-dark(#166534, #bbf7d0);
|
|
63
|
+
border: 1px solid light-dark(#86efac, #16a34a);
|
|
64
|
+
}
|
|
65
|
+
.badge.inactive {
|
|
66
|
+
background: light-dark(#f1f5f9, #27272a);
|
|
67
|
+
color: light-dark(#64748b, #a1a1aa);
|
|
68
|
+
border: 1px solid light-dark(#cbd5e1, #3f3f46);
|
|
69
|
+
}
|
|
70
|
+
.dot {
|
|
71
|
+
width: 8px;
|
|
72
|
+
height: 8px;
|
|
73
|
+
border-radius: 50%;
|
|
74
|
+
display: inline-block;
|
|
75
|
+
}
|
|
76
|
+
.dot.on { background: #22c55e; }
|
|
77
|
+
.dot.off { background: #94a3b8; }
|
|
78
|
+
.grid-2 {
|
|
79
|
+
display: grid;
|
|
80
|
+
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
|
81
|
+
gap: 14px;
|
|
82
|
+
}
|
|
83
|
+
.card {
|
|
84
|
+
@apply --vertical;
|
|
85
|
+
gap: 10px;
|
|
86
|
+
padding: 14px 16px;
|
|
87
|
+
border-radius: 8px;
|
|
88
|
+
border: 1px solid var(--border-color, #cbd5e1);
|
|
89
|
+
background: var(--content-background, #ffffff);
|
|
90
|
+
}
|
|
91
|
+
.section-title {
|
|
92
|
+
font-weight: 700;
|
|
93
|
+
font-size: 12px;
|
|
94
|
+
text-transform: uppercase;
|
|
95
|
+
letter-spacing: 0.04em;
|
|
96
|
+
opacity: 0.75;
|
|
97
|
+
border-bottom: 1px solid var(--border-color, #e2e8f0);
|
|
98
|
+
padding-bottom: 6px;
|
|
99
|
+
}
|
|
100
|
+
.kv-row {
|
|
101
|
+
@apply --horizontal;
|
|
102
|
+
justify-content: space-between;
|
|
103
|
+
align-items: center;
|
|
104
|
+
gap: 10px;
|
|
105
|
+
padding: 5px 0;
|
|
106
|
+
border-bottom: 1px solid var(--border-color, #f1f5f9);
|
|
107
|
+
font-size: 12.5px;
|
|
108
|
+
}
|
|
109
|
+
.kv-label {
|
|
110
|
+
opacity: 0.75;
|
|
111
|
+
}
|
|
112
|
+
.kv-val {
|
|
113
|
+
font-weight: 600;
|
|
114
|
+
text-align: right;
|
|
115
|
+
}
|
|
116
|
+
.pill {
|
|
117
|
+
font-size: 11px;
|
|
118
|
+
padding: 2px 7px;
|
|
119
|
+
border-radius: 4px;
|
|
120
|
+
border: 1px solid var(--border-color, #cbd5e1);
|
|
121
|
+
background: var(--subtle-background, #f8fafc);
|
|
122
|
+
}
|
|
123
|
+
.btn {
|
|
124
|
+
display: inline-flex;
|
|
125
|
+
align-items: center;
|
|
126
|
+
gap: 6px;
|
|
127
|
+
padding: 6px 14px;
|
|
128
|
+
font-size: 12.5px;
|
|
129
|
+
font-weight: 600;
|
|
130
|
+
border-radius: 6px;
|
|
131
|
+
border: 1px solid var(--border-color, #cbd5e1);
|
|
132
|
+
background: var(--subtle-background, #f1f5f9);
|
|
133
|
+
color: inherit;
|
|
134
|
+
cursor: pointer;
|
|
135
|
+
}
|
|
136
|
+
.btn.primary {
|
|
137
|
+
background: var(--accent-color, #2563eb);
|
|
138
|
+
border-color: var(--accent-color, #2563eb);
|
|
139
|
+
color: #ffffff;
|
|
140
|
+
}
|
|
141
|
+
.btn.danger {
|
|
142
|
+
color: light-dark(#b91c1c, #fca5a5);
|
|
143
|
+
border-color: light-dark(#fecaca, #7f1d1d);
|
|
144
|
+
}
|
|
145
|
+
textarea {
|
|
146
|
+
padding: 8px 10px;
|
|
147
|
+
font-size: 13px;
|
|
148
|
+
font-family: inherit;
|
|
149
|
+
border: 1px solid var(--border-color, #cbd5e1);
|
|
150
|
+
border-radius: 6px;
|
|
151
|
+
background: var(--content-background, #ffffff);
|
|
152
|
+
color: inherit;
|
|
153
|
+
resize: vertical;
|
|
154
|
+
}
|
|
155
|
+
.reply-box {
|
|
156
|
+
padding: 10px 12px;
|
|
157
|
+
border-radius: 6px;
|
|
158
|
+
border: 1px solid var(--border-color, #cbd5e1);
|
|
159
|
+
background: var(--subtle-background, #f8fafc);
|
|
160
|
+
white-space: pre-wrap;
|
|
161
|
+
line-height: 1.45;
|
|
162
|
+
font-size: 13px;
|
|
163
|
+
}
|
|
164
|
+
.msg {
|
|
165
|
+
padding: 8px 12px;
|
|
166
|
+
border-radius: 6px;
|
|
167
|
+
font-size: 12.5px;
|
|
168
|
+
}
|
|
169
|
+
.msg.ok {
|
|
170
|
+
background: light-dark(#dcfce7, #14532d);
|
|
171
|
+
color: light-dark(#166534, #bbf7d0);
|
|
172
|
+
}
|
|
173
|
+
.msg.err {
|
|
174
|
+
background: light-dark(#fee2e2, #450a0a);
|
|
175
|
+
color: light-dark(#991b1b, #fecaca);
|
|
176
|
+
}
|
|
177
|
+
</style>
|
|
5
178
|
|
|
6
|
-
|
|
179
|
+
<div class="header-card" ~if="info">
|
|
180
|
+
<div class="header-left">
|
|
181
|
+
<oda-icon :icon="info.icon || 'carbon:machine-learning-model'" icon-size="30"></oda-icon>
|
|
182
|
+
<div>
|
|
183
|
+
<div class="title">{{info.label || info.id}}</div>
|
|
184
|
+
<div class="subtitle">Провайдер: {{providerName}} · Путь: {{info.path}}</div>
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
<div class="toolbar">
|
|
188
|
+
<span class="badge" ~class="info.aiActive ? 'active' : 'inactive'">
|
|
189
|
+
<span class="dot" ~class="info.aiActive ? 'on' : 'off'"></span>
|
|
190
|
+
<span>{{info.aiActive ? 'Активна' : ('Неактивна: ' + (info.aiStatusReason || 'не настроена'))}}</span>
|
|
191
|
+
</span>
|
|
192
|
+
<label class="toolbar" style="cursor:pointer;font-weight:600;">
|
|
193
|
+
<input type="checkbox" :checked="modelEnabled" @change="toggleEnabled($event.target.checked)">
|
|
194
|
+
<span>Включена</span>
|
|
195
|
+
</label>
|
|
196
|
+
<button type="button" class="btn danger" ~if="isLocalModel" @tap="deleteModel()">Удалить с диска</button>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
|
|
200
|
+
<div class="msg ok" ~if="notice">{{notice}}</div>
|
|
201
|
+
<div class="msg err" ~if="error">{{error}}</div>
|
|
202
|
+
|
|
203
|
+
<div class="grid-2" ~if="info">
|
|
204
|
+
<div class="card">
|
|
205
|
+
<div class="section-title">Параметры модели</div>
|
|
206
|
+
<div class="kv-row">
|
|
207
|
+
<span class="kv-label">Идентификатор модели (API):</span>
|
|
208
|
+
<span class="kv-val"><code>{{info.DATA?.model || info.id}}</code></span>
|
|
209
|
+
</div>
|
|
210
|
+
<div class="kv-row">
|
|
211
|
+
<span class="kv-label">Протокол:</span>
|
|
212
|
+
<span class="kv-val">{{info.DATA?.protocol || 'openai'}}</span>
|
|
213
|
+
</div>
|
|
214
|
+
<div class="kv-row">
|
|
215
|
+
<span class="kv-label">Размер контекста (maxTokens):</span>
|
|
216
|
+
<span class="kv-val">{{info.maxTokens || info.DATA?.maxTokens || 32768}} токенов</span>
|
|
217
|
+
</div>
|
|
218
|
+
<div class="kv-row">
|
|
219
|
+
<span class="kv-label">Макс. длина ответа (maxOutput):</span>
|
|
220
|
+
<span class="kv-val">{{info.maxOutput || info.DATA?.maxOutput || 8192}} токенов</span>
|
|
221
|
+
</div>
|
|
222
|
+
<div class="kv-row" ~if="info.DATA?.baseUrl">
|
|
223
|
+
<span class="kv-label">Адрес API (Base URL):</span>
|
|
224
|
+
<span class="kv-val" style="word-break:break-all;"><code>{{info.DATA.baseUrl}}</code></span>
|
|
225
|
+
</div>
|
|
226
|
+
<div class="kv-row">
|
|
227
|
+
<span class="kv-label">Возможности:</span>
|
|
228
|
+
<div class="toolbar" style="justify-content:flex-end;">
|
|
229
|
+
<span class="pill" ~for="capabilities">{{$for.item}}</span>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
233
|
+
|
|
234
|
+
<div class="card">
|
|
235
|
+
<div class="section-title">Быстрая проверка ответа</div>
|
|
236
|
+
<textarea rows="3" :value="testPrompt" placeholder="Введите тестовый вопрос к модели…" @input="testPrompt = $this.value"></textarea>
|
|
237
|
+
<div class="toolbar">
|
|
238
|
+
<button type="button" class="btn primary" :disabled="testing" @tap="runTestPrompt()">
|
|
239
|
+
{{testing ? 'Ожидание ответа…' : 'Отправить запрос'}}
|
|
240
|
+
</button>
|
|
241
|
+
</div>
|
|
242
|
+
<div class="reply-box" ~if="testReply">{{testReply}}</div>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
`,
|
|
246
|
+
info: null,
|
|
247
|
+
modelEnabled: true,
|
|
248
|
+
testPrompt: 'Привет! Представься коротко в одном предложении.',
|
|
249
|
+
testReply: '',
|
|
250
|
+
testing: false,
|
|
251
|
+
notice: '',
|
|
252
|
+
error: '',
|
|
253
|
+
get providerName() {
|
|
254
|
+
const parts = String(this.info?.path || this.$item?.path || '').split('/').filter(Boolean);
|
|
255
|
+
return parts[1] || 'MODELS';
|
|
256
|
+
},
|
|
257
|
+
get isLocalModel() {
|
|
258
|
+
return String(this.info?.path || this.$item?.path || '').startsWith('/MODELS/Local/');
|
|
259
|
+
},
|
|
260
|
+
get capabilities() {
|
|
261
|
+
const c = this.info?.capabilities || this.info?.DATA?.capabilities || ['chat', 'stream'];
|
|
262
|
+
return Array.isArray(c) ? c : String(c).split(/[\s,]+/).filter(Boolean);
|
|
263
|
+
},
|
|
264
|
+
async attached() {
|
|
265
|
+
await this.reload();
|
|
266
|
+
},
|
|
267
|
+
async reload() {
|
|
268
|
+
if (!this.$item)
|
|
269
|
+
return;
|
|
270
|
+
try {
|
|
271
|
+
const inf = await this.$item.fetch('info');
|
|
272
|
+
this.info = inf;
|
|
273
|
+
this.modelEnabled = inf?.DATA?.enabled !== false;
|
|
274
|
+
}
|
|
275
|
+
catch (e) {
|
|
276
|
+
this.error = String(e?.message || e);
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
_refreshTree() {
|
|
280
|
+
for (const w of [window, window.parent, window.top]) {
|
|
281
|
+
try {
|
|
282
|
+
const wk = w?.WORK;
|
|
283
|
+
if (!wk?.items)
|
|
284
|
+
continue;
|
|
285
|
+
for (const k of Object.keys(wk.items)) {
|
|
286
|
+
if (k === '/MODELS' || k.startsWith('/MODELS/')) {
|
|
287
|
+
const node = wk.items[k];
|
|
288
|
+
if (node?.[w.R]?.cache)
|
|
289
|
+
delete node[w.R].cache.items;
|
|
290
|
+
node?.reset?.();
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
catch { /* ignore */ }
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
async toggleEnabled(checked) {
|
|
298
|
+
this.error = '';
|
|
299
|
+
this.notice = '';
|
|
300
|
+
if (!this.$item)
|
|
301
|
+
return;
|
|
302
|
+
try {
|
|
303
|
+
await this.$item.fetch('provider_toggle_model', {
|
|
304
|
+
nodePath: this.$item.path,
|
|
305
|
+
enabled: checked,
|
|
306
|
+
});
|
|
307
|
+
await this.reload();
|
|
308
|
+
this._refreshTree();
|
|
309
|
+
this.notice = checked ? 'Модель включена.' : 'Модель отключена.';
|
|
310
|
+
}
|
|
311
|
+
catch (e) {
|
|
312
|
+
this.error = String(e?.message || e);
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
async deleteModel() {
|
|
316
|
+
if (!this.$item || !this.isLocalModel)
|
|
317
|
+
return;
|
|
318
|
+
this.error = '';
|
|
319
|
+
try {
|
|
320
|
+
await this.$item.fetch('trainer_delete_model', { modelId: this.$item.id });
|
|
321
|
+
this._refreshTree();
|
|
322
|
+
this.notice = 'Модель и её веса удалены с диска.';
|
|
323
|
+
}
|
|
324
|
+
catch (e) {
|
|
325
|
+
this.error = String(e?.message || e);
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
async runTestPrompt() {
|
|
329
|
+
if (!this.$item || !this.testPrompt.trim())
|
|
330
|
+
return;
|
|
331
|
+
this.testing = true;
|
|
332
|
+
this.error = '';
|
|
333
|
+
this.testReply = '';
|
|
334
|
+
try {
|
|
335
|
+
const res = await this.$item.fetch('chat', {
|
|
336
|
+
messages: [{ role: 'user', content: this.testPrompt.trim() }],
|
|
337
|
+
});
|
|
338
|
+
this.testReply = String(res?.content ?? res?.text ?? JSON.stringify(res));
|
|
339
|
+
}
|
|
340
|
+
catch (e) {
|
|
341
|
+
this.error = String(e?.message || e);
|
|
342
|
+
}
|
|
343
|
+
finally {
|
|
344
|
+
this.testing = false;
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/** Мета хендлера form/provider (
|
|
1
|
+
/** Мета хендлера form/provider (Модели ИИ и подключение облачного провайдера). */
|
|
2
2
|
export default {
|
|
3
|
-
icon: 'carbon:
|
|
4
|
-
label: '
|
|
3
|
+
icon: 'carbon:chip',
|
|
4
|
+
label: 'Модели ИИ',
|
|
5
5
|
roles: ['BOSS'],
|
|
6
6
|
order: 1,
|
|
7
7
|
allowUse($context) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/** Мета хендлера form/trainer (
|
|
1
|
+
/** Мета хендлера form/trainer (Модели ИИ для локального провайдера /MODELS/Local). */
|
|
2
2
|
export default {
|
|
3
|
-
icon: 'carbon:
|
|
4
|
-
label: '
|
|
3
|
+
icon: 'carbon:chip',
|
|
4
|
+
label: 'Модели ИИ',
|
|
5
5
|
roles: ['BOSS'],
|
|
6
6
|
order: 1,
|
|
7
7
|
allowUse($context) {
|