Files
html/api/ambre-session-context.php

98 lines
4.3 KiB
PHP

<?php
/**
* ambre-session-context.php — shared helper for generation APIs
* Loads conversation context (recent topics, last docs generated) to enrich LLM prompt
* Zero confidential data exposure (per-IP session storage only)
*/
define('WVIA_SESS_DIR', '/var/tmp/wvia-pub-sessions');
define('WVIA_TTL_DAYS', 30);
if (!function_exists('wvia_sid')) {
function wvia_sid() {
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'] ?? 'unknown';
$ip = preg_replace('/[^0-9a-f.:]/i', '', $ip);
$cookie_sid = $_COOKIE['wvia_sid'] ?? '';
$cookie_sid = preg_replace('/[^a-zA-Z0-9_-]/', '', $cookie_sid);
if ($cookie_sid && strlen($cookie_sid) >= 8) return 'c_' . substr($cookie_sid, 0, 32);
return 'ip_' . md5($ip);
}
}
if (!function_exists('wvia_session_path')) {
function wvia_session_path($sid) { return WVIA_SESS_DIR . '/' . $sid . '.json'; }
}
if (!function_exists('wvia_load_session')) {
function wvia_load_session($sid = null) {
if ($sid === null) $sid = wvia_sid();
$p = wvia_session_path($sid);
if (!file_exists($p)) return null;
$raw = @file_get_contents($p);
if (!$raw) return null;
$data = @json_decode($raw, true);
if (!is_array($data)) return null;
return $data;
}
}
if (!function_exists('wvia_append_turn')) {
function wvia_append_turn($role, $content, $sid = null) {
if ($sid === null) $sid = wvia_sid();
if (!is_dir(WVIA_SESS_DIR)) { @mkdir(WVIA_SESS_DIR, 0777, true); }
$data = wvia_load_session($sid) ?: ['history'=>[], 'docs'=>[], 'topics'=>[], 'created'=>time(), 'updated'=>time()];
if (!isset($data['history'])) $data['history'] = [];
$data['history'][] = ['role'=>$role, 'content'=>substr($content, 0, 8000), 'ts'=>time()];
if (count($data['history']) > 200) $data['history'] = array_slice($data['history'], -200);
$data['updated'] = time();
@file_put_contents(wvia_session_path($sid), json_encode($data));
}
}
if (!function_exists('wvia_link_doc')) {
function wvia_link_doc($url, $kind, $title, $sid = null) {
if ($sid === null) $sid = wvia_sid();
if (!is_dir(WVIA_SESS_DIR)) { @mkdir(WVIA_SESS_DIR, 0777, true); }
$data = wvia_load_session($sid) ?: ['history'=>[], 'docs'=>[], 'topics'=>[], 'created'=>time(), 'updated'=>time()];
if (!isset($data['docs'])) $data['docs'] = [];
$data['docs'][] = ['url'=>$url, 'kind'=>$kind, 'title'=>$title, 'ts'=>time()];
if (count($data['docs']) > 50) $data['docs'] = array_slice($data['docs'], -50);
$data['updated'] = time();
@file_put_contents(wvia_session_path($sid), json_encode($data));
}
}
if (!function_exists('wvia_context_for_prompt')) {
/**
* Build context preamble to enrich LLM prompts
* Returns string with recent topics and previously generated docs
* Safe: zero internal/secret data exposed
*/
function wvia_context_for_prompt($sid = null, $max_topics = 5, $max_docs = 3) {
$data = wvia_load_session($sid);
if (!$data) return '';
$parts = [];
// Recent topics (user inputs only, truncated)
$topics = array_slice($data['topics'] ?? [], -$max_topics);
if (count($topics) > 0) {
$parts[] = "CONTEXTE CONVERSATION (sujets récents abordés par l'utilisateur):\n- " . implode("\n- ", array_map(function($t){ return substr($t, 0, 150); }, $topics));
}
// Previous docs generated
$docs = array_slice($data['docs'] ?? [], -$max_docs);
if (count($docs) > 0) {
$doc_list = [];
foreach ($docs as $d) {
$doc_list[] = ($d['kind'] ?? 'doc') . ': ' . ($d['title'] ?? 'sans titre');
}
$parts[] = "DOCUMENTS DÉJÀ GÉNÉRÉS DANS CETTE SESSION (pour cohérence/enrichissement progressif):\n- " . implode("\n- ", $doc_list);
}
if (empty($parts)) return '';
return "\n\n=== CONTEXTE SESSION ===\n" . implode("\n\n", $parts) . "\n\nIMPORTANT: Tiens compte de ce contexte pour produire un contenu qui ENRICHIT la conversation en cours (pas de redite des topics précédents, complète et approfondit au lieu).\n=== FIN CONTEXTE ===\n\n";
}
}