qwen3:8b вместо qwen2.5, отмена правки и пересоздание тегов
Замер на наших задачах (разбор 8 фраз + теги для 6 предметов):
qwen2.5:7b разбор 8/8, но теги «электротool Makita», «вoltage meter»
(первая буква кириллическая), «многофункциональный мера» —
модель думает по-английски и переводит на ходу;
qwen3:8b разбор 8/8, теги на нормальном русском.
Плата — примерно на треть медленнее на тегах. Теги важнее: по ним вещь
и находится.
Поддержка моделей-ризонеров: ollama.chat получил think=False. Без него
qwen3 тратит весь бюджет ответа на внутренний монолог и возвращает пустой
content — на первом прогоне модель выглядела нерабочей.
Разбор ответа с тегами укреплён: qwen3 иногда присылает объект
{"name":..., "synonyms":[...]} вместо списка строк, и он попадал в теги
целиком как строка. Теперь достаётся вложенный список, отсеиваются дубликаты
в разном регистре, вложенные объекты, bool и слишком длинные строки.
По замечаниям Алекса в правке предмета:
- кнопка «Отмена» — раньше открытую форму можно было только сохранить или
удалить вещь целиком;
- кнопка «🔄 Пересоздать теги» — после смены модели теги остаются старыми,
и это способ обновить их, не перезаводя вещь. Новый список показывается,
но не сохраняется молча: его ещё можно поправить руками.
В README добавлен раздел «Какую модель выбрать» с замерами и требованиями
к своей модели для тех, кто ставит приложение себе.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+39
-2
@@ -712,11 +712,16 @@ function itemEditor(it, cardEl) {
|
||||
+ '<label>Заметка</label><input class="eNote">'
|
||||
+ '<label>Теги для поиска</label><div class="tags eTags"></div>'
|
||||
+ '<input class="eNewTag mt" placeholder="добавить тег и нажать Enter">'
|
||||
+ '<div class="acts">'
|
||||
+ '<button class="eRetag">🔄 Пересоздать теги</button>'
|
||||
+ '</div>'
|
||||
+ '<p class="editHint">Тег убирается нажатием на ×. По тегам вещь и находится, '
|
||||
+ 'так что лишние лучше убрать, а свои — добавить.</p>'
|
||||
+ 'так что лишние лучше убрать, а свои — добавить. «Пересоздать» просит модель '
|
||||
+ 'придумать их заново — полезно после смены модели.</p>'
|
||||
+ '<div class="acts">'
|
||||
+ '<button class="eSave">Сохранить</button>'
|
||||
+ '<button class="eDel warn">🗑 Удалить запись</button>'
|
||||
+ '<button class="eCancel">Отмена</button>'
|
||||
+ '<button class="eDel warn">🗑 Удалить</button>'
|
||||
+ '</div>';
|
||||
|
||||
const q = s => box.querySelector(s);
|
||||
@@ -768,6 +773,38 @@ function itemEditor(it, cardEl) {
|
||||
} finally { btn.disabled = false; }
|
||||
};
|
||||
|
||||
// Отмена: закрыть правку, вернув поля к тому, что было. Без неё случайное
|
||||
// изменение можно было только сохранить или удалить вещь целиком.
|
||||
q('.eCancel').onclick = () => {
|
||||
q('.eName').value = it.name || '';
|
||||
q('.eQty').value = it.qty || '';
|
||||
q('.eNote').value = it.note || '';
|
||||
tags = (it.aliases || []).slice();
|
||||
drawTags();
|
||||
q('.eNewTag').value = '';
|
||||
box.hidden = true;
|
||||
cardEl.classList.remove('wide');
|
||||
};
|
||||
|
||||
q('.eRetag').onclick = async () => {
|
||||
const btn = q('.eRetag');
|
||||
btn.disabled = true;
|
||||
const was = btn.textContent;
|
||||
btn.textContent = 'Думаю…';
|
||||
try {
|
||||
const d = await api('/api/item/' + encodeURIComponent(it.id) + '/retag',
|
||||
{method:'POST'});
|
||||
say(d.reply);
|
||||
if (d.ok && d.item) {
|
||||
// Показываем сразу, но не сохраняем молча: список ещё можно поправить
|
||||
// руками, а «Сохранить» закрепит его.
|
||||
tags = (d.item.aliases || []).slice();
|
||||
it.aliases = tags.slice();
|
||||
drawTags();
|
||||
}
|
||||
} finally { btn.disabled = false; btn.textContent = was; }
|
||||
};
|
||||
|
||||
q('.eDel').onclick = async () => {
|
||||
if (!confirm('Удалить «' + (it.name || '') + '» из памяти?')) return;
|
||||
const d = await api('/api/item/' + encodeURIComponent(it.id), {method:'DELETE'});
|
||||
|
||||
Reference in New Issue
Block a user