pub trait AIProvider: Send + Sync {
// Required methods
fn extract<'life0, 'async_trait>(
&'life0 self,
content: String,
schema: Value,
) -> Pin<Box<dyn Future<Output = Result<Value>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn stream_extract<'life0, 'async_trait>(
&'life0 self,
content: String,
schema: Value,
) -> Pin<Box<dyn Future<Output = Result<BoxStream<'static, Result<Value>>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn capabilities(&self) -> ProviderCapabilities;
fn name(&self) -> &'static str;
}Expand description
AI Provider port for LLM-based extraction
All LLM providers (Claude, GPT, Gemini, GitHub Copilot, Ollama) implement this trait.
Uses async_trait for dyn compatibility with service registry.
§Example Implementation
use stygian_graph::ports::{AIProvider, ProviderCapabilities};
use stygian_graph::domain::error::Result;
use async_trait::async_trait;
use serde_json::{json, Value};
use futures::stream::{Stream, BoxStream};
struct MyProvider;
#[async_trait]
impl AIProvider for MyProvider {
async fn extract(&self, content: String, schema: Value) -> Result<Value> {
Ok(json!({"extracted": "data"}))
}
async fn stream_extract(
&self,
content: String,
schema: Value,
) -> Result<BoxStream<'static, Result<Value>>> {
unimplemented!("Streaming not supported")
}
fn capabilities(&self) -> ProviderCapabilities {
ProviderCapabilities {
streaming: false,
vision: false,
tool_use: true,
json_mode: true,
}
}
fn name(&self) -> &'static str {
"my-provider"
}
}Required Methods§
Sourcefn extract<'life0, 'async_trait>(
&'life0 self,
content: String,
schema: Value,
) -> Pin<Box<dyn Future<Output = Result<Value>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn extract<'life0, 'async_trait>(
&'life0 self,
content: String,
schema: Value,
) -> Pin<Box<dyn Future<Output = Result<Value>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Extract structured data from content using LLM
§Arguments
content- Raw content to analyze (text, HTML, etc.)schema- JSON schema defining expected output structure
§Returns
Ok(Value)- Extracted data matching the schemaErr(ProviderError)- API error, token limit, or policy violation
§Example
let schema = json!({
"type": "object",
"properties": {
"title": {"type": "string"},
"price": {"type": "number"}
}
});
let result = provider.extract("<html>...</html>".to_string(), schema).await.unwrap();
println!("Extracted: {}", result);Sourcefn stream_extract<'life0, 'async_trait>(
&'life0 self,
content: String,
schema: Value,
) -> Pin<Box<dyn Future<Output = Result<BoxStream<'static, Result<Value>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn stream_extract<'life0, 'async_trait>(
&'life0 self,
content: String,
schema: Value,
) -> Pin<Box<dyn Future<Output = Result<BoxStream<'static, Result<Value>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Stream structured data extraction for real-time processing
Returns a stream of partial results as they arrive from the LLM.
Only supported by providers with capabilities().streaming == true.
§Arguments
content- Raw content to analyzeschema- JSON schema defining expected output structure
§Returns
Ok(BoxStream)- Stream of partial extraction resultsErr(ProviderError)- If streaming is not supported or API error
§Example
let schema = json!({"type": "object"});
let mut stream = provider.stream_extract("content".to_string(), schema).await.unwrap();
while let Some(result) = stream.next().await {
match result {
Ok(partial) => println!("Chunk: {}", partial),
Err(e) => eprintln!("Stream error: {}", e),
}
}Sourcefn capabilities(&self) -> ProviderCapabilities
fn capabilities(&self) -> ProviderCapabilities
Get provider capabilities
Returns a struct describing what features this provider supports.
§Example
let caps = provider.capabilities();
if caps.streaming {
println!("Provider supports streaming");
}
if caps.vision {
println!("Provider supports image analysis");
}