Files
momentry_core/src/api/agent_api.rs
T
Accusys 2cfcfdd1af feat: Phase 2.6 edges migration to Qdrant (TKG-only architecture)
Phase 2.6.1: co_occurrence_edges migration
- build_co_occurrence_edges_from_qdrant()
- Qdrant embeddings → frame grouping → YOLO objects
- Result: 6679 edges (vs 6701 PostgreSQL)

Phase 2.6.2: face_face_edges migration
- build_face_face_edges_from_qdrant()
- Qdrant embeddings → frame grouping → face pairs
- mutual_gaze detection preserved
- Result: 6 edges (exact match)

Phase 2.6.3: speaker_face_edges migration
- build_speaker_face_edges_from_qdrant()
- Qdrant embeddings → trace_id frame ranges
- SPEAKS_AS edge creation

Architecture:
- All edges use Qdrant payload (no face_detections queries)
- PostgreSQL fallback for empty Qdrant
- Estimated 3.6x performance improvement

Testing:
- Playground (3003): ✓ All Phase 2.6 logs verified
- Edge counts: ✓ Close match with PostgreSQL
- Fallback: ✓ Working

Docs:
- docs_v1.0/DESIGN/TKG_PHASE2_6_EDGES_MIGRATION.md
- docs_v1.0/M4_workspace/2026-06-21_phase2_6_test.md
2026-06-21 04:47:49 +08:00

90 lines
2.8 KiB
Rust

use axum::{extract::State, http::StatusCode, response::Json, routing::post, Router};
use serde::{Deserialize, Serialize};
use crate::api::types::AppState;
use crate::core::llm::function_calling::LLM_CLIENT;
pub fn agent_routes() -> Router<AppState> {
Router::new().route("/api/v1/agents/translate", post(translate_text))
}
#[derive(Debug, Deserialize)]
pub struct TranslationRequest {
pub text: String,
pub target_language: String,
pub source_language: Option<String>, // "auto" if not specified
}
#[derive(Debug, Serialize)]
pub struct TranslationResponse {
pub success: bool,
pub translated_text: String,
pub source_language_detected: String,
pub model_used: String,
}
async fn translate_text(
State(_state): State<AppState>,
Json(req): Json<TranslationRequest>,
) -> Result<Json<TranslationResponse>, (StatusCode, String)> {
let system_prompt = "You are a professional translator for Momentry Core, a digital asset management system specializing in video analysis.
## Guidelines:
1. **Accuracy**: Translate the meaning accurately, maintaining the original tone.
2. **Style**:
- For subtitles: Keep it concise and natural for reading.
- For technical terms (e.g., 5W1H, metadata): Use standard industry translations.
3. **Output**: Return ONLY the translated text. Do not include explanations or notes.";
let prompt = format!(
"Translate the following text to {}: \n\n{}",
req.target_language, req.text
);
// Call LLM via configurable endpoint
let llm_url = crate::core::config::llm::CHAT_URL.as_str();
let model = crate::core::config::llm::CHAT_MODEL.as_str();
let body = serde_json::json!({
"model": model,
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": prompt}
],
"stream": false,
"max_tokens": 1024,
"temperature": 0.1
});
let response = LLM_CLIENT
.post(llm_url)
.json(&body)
.send()
.await
.map_err(|e| {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Failed to call LLM: {}", e),
)
})?;
let llm_resp: serde_json::Value = response.json().await.map_err(|e| {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Failed to parse LLM response: {}", e),
)
})?;
let translated_text = llm_resp["choices"][0]["message"]["content"]
.as_str()
.unwrap_or("")
.to_string();
Ok(Json(TranslationResponse {
success: true,
translated_text,
source_language_detected: req.source_language.unwrap_or_else(|| "auto".to_string()),
model_used: model.to_string(),
}))
}