6ed30ff042
- v4 (stand4.py): наставник=всегда хайку, оператор=лёгкий промпт с маршрутом эталона (флэш на простое/хайку на сложное). На диалоге продаж флэш не включается — всё сложное; выигрыш скорости даёт лёгкий промпт (10x), а не смена модели. - v5 (stand5.py): ПРИГВОЖДЁННЫЕ ФАКТЫ (числа дословно, запрет арифметики/производных) — баг с домысленными числами закрыт для haiku-оператора; +3 простых хода → флэш включился (ход-подтверждение ~0.8с), качество вровень/лучше эталонного флэша. - фикс ловушки STOP_RE: долг(?![оаие]) — долгая/надолго/недолго больше не считаются горем (только в стенде; эталон на сервере не тронут). - дописан раздел 4а + обновлены шапка/стартовый блок в находках. FLOOR-ESCAPE: владелец разрешил коммит. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
94 lines
5.5 KiB
Python
94 lines
5.5 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""СТЕНД v4 — ГИБРИД-МАРШРУТ, как просил владелец.
|
||
• наставник = ВСЕГДА хайку (умный, вне пути; из v2 mentor_hint2);
|
||
• оператор = ЛЁГКИЙ промпт (OP2_SYS из v2), но модель выбирается маршрутом ЭТАЛОНА:
|
||
простой ход → флэш-лайт (шустрая, дёшево)
|
||
сложный/«стоп»/1-й → хайку (умная подхватывает тяжёлое)
|
||
То есть «хайку на сложное, флэш на простое» + острая подсказка хайку-наставника.
|
||
Рядом кладём ЭТАЛОН (толстый промпт, тот же маршрут) — владелец судит качество.
|
||
Один диалог (демо-стоматолог). Сервер/эталонный движок/Cartesia не трогаем.
|
||
"""
|
||
import os
|
||
import stand as S
|
||
import stand2 as S2
|
||
|
||
SMART, FAST = S.SMART, S.FAST
|
||
NICHE, BRIEF = S.NICHE, S.BRIEF
|
||
|
||
|
||
def pick_operator_model(client_turn, turn_idx):
|
||
"""Маршрут эталона, но правит моделью ОПЕРАТОРА (лёгкий промпт)."""
|
||
kind = S.classify(client_turn)
|
||
m = S.mood(client_turn)
|
||
hard = (m == "СТОП" or kind == "СЛОЖНЫЙ" or turn_idx == 0)
|
||
return (SMART if hard else FAST), kind, m
|
||
|
||
|
||
def main():
|
||
out = []
|
||
def P(s=""):
|
||
print(s, flush=True); out.append(s)
|
||
|
||
P(f"СТЕНД v4 «гибрид-маршрут» · ниша={NICHE}")
|
||
P("наставник=ВСЕГДА хайку · оператор=лёгкий промпт, модель: простой→флэш, сложный/стоп/1й→хайку")
|
||
P(f"АЛЕКСАНДРА (приветствие): {S.GREETING}\n")
|
||
|
||
hist_old = [{"role": "assistant", "content": S.GREETING}]
|
||
hist_new = [{"role": "assistant", "content": S.GREETING}]
|
||
agg = {"old_pt": 0, "old_t": 0.0, "op_pt": 0, "op_t": 0.0,
|
||
"men_t": 0.0, "men_pt": 0, "pospel": 0, "flash": 0, "haiku": 0}
|
||
|
||
for i, ct in enumerate(S.CLIENT_TURNS):
|
||
cdur = S.dur_of(ct)
|
||
|
||
# ── ЭТАЛОН (толстый промпт, тот же маршрут) ──
|
||
op_model, kind, m = pick_operator_model(ct, i)
|
||
msgs_old = [{"role": "system", "content": S.build_sys_old(NICHE, BRIEF)}] + hist_old + [{"role": "user", "content": ct}]
|
||
old_txt, old_pt, _, old_dt = S.chat(op_model, msgs_old, max_tokens=400)
|
||
|
||
# ── наставник (всегда хайку, вне пути) ──
|
||
hint, men_pt, _, men_dt = S2.mentor_hint2(hist_new, ct)
|
||
pospel = men_dt <= cdur
|
||
use_hint = S2.HINT0 if i == 0 else hint # ход 1 — заготовка (наставник не поспевает)
|
||
|
||
# ── оператор (лёгкий промпт, модель по маршруту) ──
|
||
op_sys = S2.OP2_SYS.format(hint=use_hint)
|
||
msgs_op = [{"role": "system", "content": op_sys}] + hist_new[-2:] + [{"role": "user", "content": ct}]
|
||
op_txt, op_pt, _, op_dt = S.chat(op_model, msgs_op, max_tokens=400, temperature=0.6)
|
||
|
||
agg["old_pt"] += old_pt; agg["old_t"] += old_dt
|
||
agg["op_pt"] += op_pt; agg["op_t"] += op_dt
|
||
agg["men_t"] += men_dt; agg["men_pt"] += men_pt; agg["pospel"] += int(pospel)
|
||
agg["flash" if op_model == FAST else "haiku"] += 1
|
||
|
||
tag = "флэш" if op_model == FAST else "ХАЙКУ"
|
||
P(f"━━━━━━━━━━ ХОД {i+1} ━━━━━━━━━━")
|
||
P(f"КЛИЕНТ: {ct} (речь ~{cdur:.1f}с)")
|
||
P(f"🧭 маршрут: {kind}/{m} → оператор на «{tag}» ({op_model})")
|
||
P(f"🧑🏫 ПОДСКАЗКА{' [заготовка]' if i==0 else ''}: {use_hint}")
|
||
if i == 0:
|
||
P(f" (наставник вживую: {men_pt}т, {men_dt:.2f}с — не поспел за {cdur:.1f}с → заготовка)")
|
||
else:
|
||
P(f" (наставник хайку вне пути: {men_pt}т, {men_dt:.2f}с · поспел? {'ДА' if pospel else 'НЕТ'})")
|
||
P(f"🐌 ЭТАЛОН [толстый, {op_model}, {old_pt}т, {old_dt:.2f}с]:\n {old_txt}")
|
||
P(f"⚡ НОВЫЙ [лёгкий, {op_model}, {op_pt}т, {op_dt:.2f}с]:\n {op_txt}")
|
||
P("")
|
||
|
||
hist_old += [{"role": "user", "content": ct}, {"role": "assistant", "content": old_txt}]
|
||
hist_new += [{"role": "user", "content": ct}, {"role": "assistant", "content": op_txt}]
|
||
|
||
n = len(S.CLIENT_TURNS)
|
||
P("═══════════════ ИТОГО ═══════════════")
|
||
P(f"Маршрут оператора: флэш {agg['flash']} ходов, хайку {agg['haiku']} ходов из {n}")
|
||
P(f"Горячий путь ПРОМПТ: ЭТАЛОН {agg['old_pt']//n}т → НОВЫЙ(оператор) {agg['op_pt']//n}т")
|
||
P(f"Горячий путь ВРЕМЯ: ЭТАЛОН {agg['old_t']/n:.2f}с → НОВЫЙ(оператор) {agg['op_t']/n:.2f}с")
|
||
P(f"Наставник (хайку, вне пути): {agg['men_pt']//n}т, {agg['men_t']/n:.2f}с · поспел {agg['pospel']}/{n}")
|
||
P("Судья — владелец: качество НОВОГО против ЭТАЛОНА по каждому ходу.")
|
||
|
||
open(os.path.join(S.HERE, "rezultat4.txt"), "w", encoding="utf-8").write("\n".join(out))
|
||
print("\n[записано в rezultat4.txt]", flush=True)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|