98 lines
4.3 KiB
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";
|
|
}
|
|
}
|