From d1e9a8e93446465b34778bfcd0bf9a5727f2150a Mon Sep 17 00:00:00 2001 From: VadimL Date: Fri, 24 Jul 2026 21:26:30 +0300 Subject: [PATCH] Added summary of user dialogue --- chat_history.db | Bin 4096 -> 0 bytes chat_history.db-shm | Bin 32768 -> 0 bytes chat_history.db-wal | Bin 679832 -> 0 bytes src/main.rs | 194 +++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 184 insertions(+), 10 deletions(-) delete mode 100644 chat_history.db delete mode 100644 chat_history.db-shm delete mode 100644 chat_history.db-wal diff --git a/chat_history.db b/chat_history.db deleted file mode 100644 index 4ebf78cf96088c7148cb47caf804cc036de75a34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmWFz^vNtqRY=P(%1ta$FlG>7U}9o$P*7lCU|@t|AVoG{WY8;GzzfnYK(-m98b?E5 nGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nC=3ArfDQ*E diff --git a/chat_history.db-shm b/chat_history.db-shm deleted file mode 100644 index 9cb537842b5b0d959f7f4a0bc5faf91602dee588..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32768 zcmeI)$4^vI6oBy$M#L_5?7gAb#V&S5u`3qr9V?2xU>7U)UQpDfd*jxB!nF%c+`HEM z2qqI2CQdTRO#DuA=bbm1bMHC7%=+ej%_oY?ureU$eRwtr>vPSI;!od7%YK&Reb4{! zG4`dZqP)7OpfdL#e;>B0i`ww{D=zB4rlvj#XV>)*3(qKT6!-o==J6iU{8?c&4lDAB z-v5?2tj&(AOO?D~kI{eb&upoZhn5Tl6i`3`1r$&~0R#$%lRQ9yR1?Syw}>>Q1+8gI2Xg634|>y&f#i|T2u4%D1SV6+4Cb(s%2XS` zeiTSpAVxOLXh{z3=tyU}(UU&(XAnae#z@96j)_cR8Z(*80v55964tPejcj2%yV%2i z4sw`doa8JQxXe{K=`Jvzg)Cutx{qQ13M3$~no>5fnQiQ3H~T23f}@<^bOL)>qCk2H zoaYi%T;~>dxX&Y=@*>>9TT68Buc3ef3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUg YfC36Apnw7jD4>7>3Mim}0_h>}8+S}%dH?_b diff --git a/chat_history.db-wal b/chat_history.db-wal deleted file mode 100644 index e98a4d287366080721b75eaa154162bb56477015..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 679832 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 Ltq6@hkKq3U>!Wdm diff --git a/src/main.rs b/src/main.rs index d3be9b8..d3e9934 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,9 +65,87 @@ async fn init_db(db_url: &str) -> Result, Box, + messages_to_summarize: &[ChatMessage], +) -> Result> { + let mut prompt = String::new(); + + if let Some(old_sum) = current_summary { + prompt.push_str(&format!( + "УЖЕ ИЗВЕСТНАЯ ПАМЯТЬ О ПОЛЬЗОВАТЕЛЕ И ЗАДАЧАХ:\n{}\n\n", + old_sum + )); + } + + prompt.push_str("НОВЫЕ СООБЩЕНИЯ ДИАЛОГА:\n"); + for msg in messages_to_summarize { + if msg.role == "user" { + prompt.push_str(&format!("User: {}\n", msg.content)); + } + } + + prompt.push_str( + r#" +ИНСТРУКЦИЯ ПО ОБНОВЛЕНИЮ ПАМЯТИ: +Проанализируй диалог и обнови накопительный профиль памяти. + +ЧТО НУЖНО СОХРАНЯТЬ (ТОЛЬКО ИЗ СООБЩЕНИЙ ПОЛЬЗОВАТЕЛЯ / USER): +1. Личные данные пользователя (имя, возраст, профессия, хобби, предпочтения, ограничения). +2. Контекст задачи или темы (над чем работаем, текущие цели, формат ответа, который просит пользователь). +3. Любые точные вводные данные (числа, имена, даты, пароли/коды, списки, специфические термины). + +КРИТИЧЕСКИ ВАЖНЫЕ ПРАВИЛА: +- ИГНОРИРУЙ справочные ответы Ассистента (Assistant). Не сохраняй в память факты, стихи, статьи или ответы на энциклопедические вопросы, которые сгенерировал Ассистент. +- Сохраняй ТОЛЬКО то, что сообщил сам Пользователь, либо явные решения/итоги, к которым пришли. +- Пиши максимально кратко, сжато, в виде маркированного списка. +- Если новые сообщения не содержат новых фактов о пользователе или его задаче — оставь существующую память без изменений. +НЕ ЗАПИСЫВАЙ: + +О чем пользователь спрашивал или интересовался (например: НЕ пиши "Спрашивал про точки Лагранжа" или "Интересуется столицами"). Записывай только утвердительные факты о самом пользователе или данные. +"#, + ); + + let payload = json!({ + "model": model, + "messages": [ + { + "role": "system", + "content": "Ты — автономный модуль памяти ассистента. Твоя единственная цель — вытаскивать и структурировать личные данные, контекст задач и явные указания ПОЛЬЗОВАТЕЛЯ. Ты не ответишь на вопросы из чата, ты только ведешь блокнот фактов." + }, + {"role": "user", "content": prompt} + ], + "temperature": 0.0 + }); + + let response = client.post(api_url).json(&payload).send().await?; + let res_body: serde_json::Value = response.json().await?; + + if let Some(summary) = res_body["choices"][0]["message"]["content"].as_str() { + Ok(summary.to_string()) + } else { + Err("Не удалось сгенерировать резюме".into()) + } +} + /// Сохранение реплики async fn save_message( pool: &Pool, @@ -85,6 +163,29 @@ async fn save_message( Ok(()) } +/// Сохранение или обновление summary для сессии (UPSERT) +async fn save_session_summary( + pool: &Pool, + session_id: &str, + summary: &str, +) -> Result<(), sqlx::Error> { + sqlx::query( + r#" + INSERT INTO session_summaries (session_id, summary, updated_at) + VALUES (?, ?, CURRENT_TIMESTAMP) + ON CONFLICT(session_id) DO UPDATE SET + summary = excluded.summary, + updated_at = CURRENT_TIMESTAMP; + "#, + ) + .bind(session_id) + .bind(summary) + .execute(pool) + .await?; + + Ok(()) +} + /// Выборка последних N сообщений async fn get_recent_history( pool: &Pool, @@ -117,18 +218,32 @@ async fn get_recent_history( Ok(history) } +async fn get_session_summary( + pool: &Pool, + session_id: &str, +) -> Result, sqlx::Error> { + let result = sqlx::query_as::<_, (String,)>( + "SELECT summary FROM session_summaries WHERE session_id = ?", + ) + .bind(session_id) + .fetch_optional(pool) + .await?; + + Ok(result.map(|(s,)| s)) +} + /// Отправка запроса с контекстом в LLM async fn send_llm_request_with_history( client: &reqwest::Client, api_url: &str, model: &str, - system_prompt: Option<&str>, // <-- Добавили системный промпт + system_prompt: Option<&str>, + summary: Option<&str>, history: &[ChatMessage], ) -> Result> { - // Собираем полный вектор сообщений let mut full_messages = Vec::new(); - // 1. Если system_prompt задан и не пустой, ставим его САМЫМ ПЕРВЫМ + // 1. Системный промпт if let Some(prompt) = system_prompt { if !prompt.trim().is_empty() { full_messages.push(ChatMessage { @@ -138,10 +253,19 @@ async fn send_llm_request_with_history( } } - // 2. Добавляем историю из базы данных (user / assistant) + // 2. Долгосрочная сжатая память (если есть) + if let Some(sum) = summary { + if !sum.trim().is_empty() { + full_messages.push(ChatMessage { + role: "system".to_string(), + content: format!("[Краткий контекст прошлых сообщений]: {}", sum), + }); + } + } + + // 3. Последние N реплик из истории full_messages.extend_from_slice(history); - // 3. Отправляем в payload уже полный вектор let payload = json!({ "model": model, "messages": full_messages, @@ -184,6 +308,7 @@ async fn main() -> Result<(), Box> { let client = reqwest::Client::new(); let db_pool = init_db(&args.db_url).await?; let system_prompt = file_config.system_prompt; + println!("=================================================="); println!(" LLM CLI Agent with Memory & Config"); println!(" Session ID: {}", session_id); @@ -192,7 +317,7 @@ async fn main() -> Result<(), Box> { println!(" History: последние {} сообщений", history_limit); println!(" Config: {}", args.config); println!("=================================================="); - println!("Введите сообщение. Для выхода наберите 'exit' или 'quit'.\n"); + println!("Введите сообщение. Служебные команды: /summary, /clear, exit\n"); let stdin = tokio::io::stdin(); let mut reader = BufReader::new(stdin); @@ -214,19 +339,42 @@ async fn main() -> Result<(), Box> { continue; } + // --- Служебные команды CLI --- if trimmed_input.eq_ignore_ascii_case("exit") || trimmed_input.eq_ignore_ascii_case("quit") { println!("Завершение работы."); break; } - // Сохраняем запрос юзера + if trimmed_input == "/summary" { + match get_session_summary(&db_pool, &session_id).await { + Ok(Some(s)) => println!("\n[Текущий Summary]:\n{}\n", s), + Ok(None) => println!("\n[Текущий Summary]: (пусто)\n"), + Err(e) => eprintln!("[Ошибка чтения summary]: {}\n", e), + } + continue; + } + + if trimmed_input == "/clear" { + let _ = sqlx::query("DELETE FROM messages WHERE session_id = ?") + .bind(&session_id) + .execute(&db_pool) + .await; + let _ = sqlx::query("DELETE FROM session_summaries WHERE session_id = ?") + .bind(&session_id) + .execute(&db_pool) + .await; + println!("\n[Память сессии '{}' очищена]\n", session_id); + continue; + } + + // 1. Сохраняем запрос юзера в историю if let Err(e) = save_message(&db_pool, &session_id, "user", trimmed_input).await { eprintln!("[Ошибка записи в БД]: {}", e); continue; } - // Вычитываем контекст (N сообщений) + // 2. Вычитываем историю и существующий summary let history = match get_recent_history(&db_pool, &session_id, history_limit).await { Ok(h) => h, Err(e) => { @@ -235,15 +383,41 @@ async fn main() -> Result<(), Box> { } }; + let mut summary = match get_session_summary(&db_pool, &session_id).await { + Ok(s) => s, + Err(e) => { + eprintln!("[Ошибка чтения summary из БД]: {}", e); + None + } + }; + + // 3. Авто-суммаризация: сжимаем контекст при накоплении >= 6 сообщений + if history.len() >= 6 { + print!("[Сжатие контекста в фоновую память...]\r"); + io::stdout().flush().unwrap(); + + if let Ok(new_summary) = + summarize_context(&client, &api_url, &model, summary.as_deref(), &history).await + { + if let Err(e) = save_session_summary(&db_pool, &session_id, &new_summary).await { + eprintln!("[Ошибка сохранения summary]: {}", e); + } else { + summary = Some(new_summary); + } + } + print!("\r\x1B[2K"); + } + + // 4. Отправляем запрос в LLM print!("[Запрос к LLM (контекст {} сообщ.)...]\r", history.len()); io::stdout().flush().unwrap(); - // Отправка в LLM match send_llm_request_with_history( &client, &api_url, &model, - system_prompt.as_deref(), // Преобразуем Option в Option<&str> + system_prompt.as_deref(), + summary.as_deref(), &history, ) .await