Add three chat profiles: Varaverk Assistant, General Chat, Code Sketcher
Explicit buttons rather than an automatic router. Misclassifying a Varaverk question as chat produces a confident invention about the user's system, which is exactly what retrieval exists to prevent — with buttons there is no hidden heuristic to be wrong and the strict profile is the default you land on. Only Varaverk Assistant retrieves; the other two would be carrying passages that cannot help write a folder-copy script. Memory goes to all three, since that is what lets chat know the setup without claiming authority over it. History depth is per profile and set server-side: retrieval costs ~2500 of 16384, so the profiles that skip it can hold a real conversation. Code Sketcher is told to flag flags it is unsure of, after it invented rsync --no-overwrite.
This commit is contained in:
@@ -89,7 +89,12 @@ header('Content-Type: application/json');
|
||||
header('Cache-Control: no-store, no-cache');
|
||||
require_once dirname(__DIR__) . '/include/ai.php';
|
||||
|
||||
const VV_AI_MAX_TURNS = 3; // user+assistant pairs retained; see OPERATIONAL MODEL
|
||||
// History depth is per profile, and decided here rather than by the page. Varaverk Assistant
|
||||
// spends ~2500 of its 16384 on retrieved passages, so it cannot afford deep history; the other
|
||||
// two retrieve nothing and can carry a real conversation. Reasoning is not stored in history,
|
||||
// so it does not compound.
|
||||
const VV_AI_PROFILES = ['varaverk' => 3, 'chat' => 8, 'code' => 4];
|
||||
const VV_AI_MAX_TURNS = 3; // fallback when a profile is not recognised
|
||||
const VV_AI_MAX_QUESTION = 4000; // characters
|
||||
const VV_AI_MAX_HIST_MSG = 4000; // characters per retained message
|
||||
const VV_AI_JOB_TTL = 3600; // seconds before a job file is reaped
|
||||
@@ -179,7 +184,14 @@ if ($action === 'ask') {
|
||||
echo json_encode(['ok' => false, 'error' => 'question exceeds ' . VV_AI_MAX_QUESTION . ' characters']); exit;
|
||||
}
|
||||
|
||||
$kind = trim($_POST['kind'] ?? '');
|
||||
$profile = trim($_POST['profile'] ?? 'varaverk');
|
||||
if (!isset(VV_AI_PROFILES[$profile])) {
|
||||
echo json_encode(['ok' => false, 'error' => 'Unknown profile: ' . $profile]); exit;
|
||||
}
|
||||
$maxTurns = VV_AI_PROFILES[$profile] ?? VV_AI_MAX_TURNS;
|
||||
|
||||
// The retrieval filter only means anything to the profile that retrieves.
|
||||
$kind = $profile === 'varaverk' ? trim($_POST['kind'] ?? '') : '';
|
||||
if ($kind !== '' && !in_array($kind, VV_AI_KINDS, true)) {
|
||||
echo json_encode(['ok' => false, 'error' => 'Unknown kind: ' . $kind]); exit;
|
||||
}
|
||||
@@ -196,8 +208,8 @@ if ($action === 'ask') {
|
||||
$clean[] = ['role' => $role, 'content' => mb_substr($text, 0, VV_AI_MAX_HIST_MSG)];
|
||||
}
|
||||
}
|
||||
if (count($clean) > VV_AI_MAX_TURNS * 2) {
|
||||
$clean = array_slice($clean, -(VV_AI_MAX_TURNS * 2));
|
||||
if (count($clean) > $maxTurns * 2) {
|
||||
$clean = array_slice($clean, -($maxTurns * 2));
|
||||
}
|
||||
|
||||
$dir = vv_ai_job_dir();
|
||||
@@ -226,12 +238,13 @@ if ($action === 'ask') {
|
||||
. escapeshellarg($question) . ' '
|
||||
. escapeshellarg(json_encode($clean)) . ' '
|
||||
. escapeshellarg($kind) . ' '
|
||||
. escapeshellarg(($_POST['think'] ?? '1') === '1' ? '1' : '0')
|
||||
. escapeshellarg(($_POST['think'] ?? '1') === '1' ? '1' : '0') . ' '
|
||||
. escapeshellarg($profile)
|
||||
. ' >/dev/null 2>&1 </dev/null &';
|
||||
$out = []; $rc = 0;
|
||||
exec($cmd, $out, $rc);
|
||||
vv_ai_log(sprintf('ask token=%s rc=%d kind=%s q=%s',
|
||||
substr($token, 0, 12), $rc, $kind ?: '-', mb_substr($question, 0, 80)));
|
||||
vv_ai_log(sprintf('ask token=%s rc=%d profile=%s kind=%s q=%s',
|
||||
substr($token, 0, 12), $rc, $profile, $kind ?: '-', mb_substr($question, 0, 80)));
|
||||
|
||||
echo json_encode(['ok' => true, 'token' => $token]);
|
||||
exit;
|
||||
|
||||
Reference in New Issue
Block a user