feat(ai): few-shot exemplars + sticky Ollama preference
- Few-shot injection on /insights/generate/agentic: compresses prior training_messages into trajectory blocks (tool calls + result summaries) and injects into the system prompt. Hardcoded default ids with optional request override. - New fewshot_source_ids column on photo_insights (+ migration) to track which exemplars influenced a given row, for downstream training-set filtering. Chat amend rows stamp None with a lineage note. - Ollama client now remembers which server (primary/fallback) most recently succeeded and tries it first on the next call, via a shared Arc<AtomicBool>. Avoids re-404ing the primary on every agent iteration when the chosen model only lives on the fallback. - Demote noisy logs: daily_summary "Summary match" lines to debug; inner chat_with_tools non-2xx body log from error to warn (outer layer owns the terminal-error signal). - Drift-guard tests for summarize_tool_result covering the success / empty / error / unknown shape for every tool. - Tidy: three pre-existing clippy warnings cleaned up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -502,6 +502,11 @@ impl InsightChatService {
|
||||
.await?;
|
||||
let title = title_raw.trim().trim_matches('"').to_string();
|
||||
|
||||
// Amended rows intentionally do not inherit the parent's
|
||||
// `fewshot_source_ids`. The parent's few-shot influence is still
|
||||
// present in this row's content; if you want strict lineage
|
||||
// tracking for training-set filtering, fetch the parent here and
|
||||
// copy its value forward.
|
||||
let new_row = InsertPhotoInsight {
|
||||
library_id: req.library_id,
|
||||
file_path: normalized.clone(),
|
||||
@@ -512,6 +517,7 @@ impl InsightChatService {
|
||||
is_current: true,
|
||||
training_messages: Some(json),
|
||||
backend: effective_backend.clone(),
|
||||
fewshot_source_ids: None,
|
||||
};
|
||||
let cx = opentelemetry::Context::new();
|
||||
let mut dao = self.insight_dao.lock().expect("Unable to lock InsightDao");
|
||||
@@ -608,7 +614,7 @@ impl InsightChatService {
|
||||
) -> BoxStream<'static, ChatStreamEvent> {
|
||||
let svc = self;
|
||||
let s = async_stream::stream! {
|
||||
match svc.chat_turn_stream_inner(req, |ev| Ok(ev)).await {
|
||||
match svc.chat_turn_stream_inner(req, Ok).await {
|
||||
Ok(mut rx) => {
|
||||
while let Some(ev) = rx.recv().await {
|
||||
yield ev;
|
||||
@@ -955,6 +961,11 @@ impl InsightChatService {
|
||||
.await?;
|
||||
let title = title_raw.trim().trim_matches('"').to_string();
|
||||
|
||||
// Amended rows intentionally do not inherit the parent's
|
||||
// `fewshot_source_ids`. The parent's few-shot influence is still
|
||||
// present in this row's content; if you want strict lineage
|
||||
// tracking for training-set filtering, fetch the parent here and
|
||||
// copy its value forward.
|
||||
let new_row = InsertPhotoInsight {
|
||||
library_id: req.library_id,
|
||||
file_path: normalized.clone(),
|
||||
@@ -965,6 +976,7 @@ impl InsightChatService {
|
||||
is_current: true,
|
||||
training_messages: Some(json),
|
||||
backend: effective_backend.clone(),
|
||||
fewshot_source_ids: None,
|
||||
};
|
||||
let cx = opentelemetry::Context::new();
|
||||
let mut dao = self.insight_dao.lock().expect("Unable to lock InsightDao");
|
||||
|
||||
Reference in New Issue
Block a user