1use anyhow::Result;
2use async_trait::async_trait;
3use locus_core_rs::domain::models::AvecState;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum AiCapability {
7 SemanticEmbedding,
8 AvecEmbedding,
9 AvecScoring,
10}
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum AiTask {
14 SemanticEmbedding,
15 AvecEmbedding,
16 AvecScoring,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum ProviderPolicy {
21 Auto,
22 Preferred,
23 Required,
24}
25
26#[derive(Debug, Clone)]
27pub struct EmbedRequest {
28 pub text: String,
29 pub task: AiTask,
30 pub provider_id: Option<String>,
31 pub model: Option<String>,
32 pub policy: ProviderPolicy,
33}
34
35#[derive(Debug, Clone)]
36pub struct ScoreAvecRequest {
37 pub text: String,
38 pub provider_id: Option<String>,
39 pub model: Option<String>,
40 pub policy: ProviderPolicy,
41}
42
43#[async_trait]
44pub trait AiProvider: Send + Sync {
45 fn provider_id(&self) -> &str;
46 fn capabilities(&self) -> &'static [AiCapability];
47
48 async fn embed_semantic(&self, request: &EmbedRequest) -> Result<Vec<f32>>;
49
50 async fn embed_avec(&self, request: &EmbedRequest) -> Result<Vec<f32>>;
51
52 async fn score_avec(&self, request: &ScoreAvecRequest) -> Result<AvecState>;
53}
54
55pub trait AiProviderRegistry: Send + Sync {
56 fn resolve(
57 &self,
58 task: AiTask,
59 provider_id: Option<&str>,
60 policy: ProviderPolicy,
61 ) -> Result<&dyn AiProvider>;
62
63 fn list_capabilities(&self) -> Vec<(String, Vec<AiCapability>)>;
64}