Phase 3: AI integration with Ollama via Python sidecar
- sidecar: FastAPI app with /embed, /generate, /rerank hitting Ollama - sidecar: Dockerfile, env var config (EMBED_MODEL, GEN_MODEL, RERANK_MODEL) - aibridge: reqwest HTTP client with typed request/response structs - aibridge: Axum proxy endpoints (POST /ai/embed, /ai/generate, /ai/rerank) - gateway: wires AiClient with SIDECAR_URL env var - e2e verified: nomic-embed-text returns 768d vectors, qwen2.5 generates text Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,60 @@
|
||||
use axum::{Router, routing::get};
|
||||
use axum::{
|
||||
Json, Router,
|
||||
extract::State,
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
routing::{get, post},
|
||||
};
|
||||
|
||||
pub fn router() -> Router {
|
||||
Router::new().route("/health", get(health))
|
||||
use crate::client::{
|
||||
AiClient, EmbedRequest, GenerateRequest, RerankRequest,
|
||||
};
|
||||
|
||||
pub fn router(client: AiClient) -> Router {
|
||||
Router::new()
|
||||
.route("/health", get(health))
|
||||
.route("/embed", post(embed))
|
||||
.route("/generate", post(generate))
|
||||
.route("/rerank", post(rerank))
|
||||
.with_state(client)
|
||||
}
|
||||
|
||||
async fn health() -> &'static str {
|
||||
"aibridge ok"
|
||||
async fn health(State(client): State<AiClient>) -> impl IntoResponse {
|
||||
match client.health().await {
|
||||
Ok(info) => Ok(Json(info)),
|
||||
Err(e) => Err((StatusCode::BAD_GATEWAY, format!("sidecar down: {e}"))),
|
||||
}
|
||||
}
|
||||
|
||||
async fn embed(
|
||||
State(client): State<AiClient>,
|
||||
Json(req): Json<EmbedRequest>,
|
||||
) -> impl IntoResponse {
|
||||
tracing::info!("embedding {} texts", req.texts.len());
|
||||
match client.embed(req).await {
|
||||
Ok(resp) => Ok(Json(resp)),
|
||||
Err(e) => Err((StatusCode::BAD_GATEWAY, e)),
|
||||
}
|
||||
}
|
||||
|
||||
async fn generate(
|
||||
State(client): State<AiClient>,
|
||||
Json(req): Json<GenerateRequest>,
|
||||
) -> impl IntoResponse {
|
||||
tracing::info!("generating with prompt len={}", req.prompt.len());
|
||||
match client.generate(req).await {
|
||||
Ok(resp) => Ok(Json(resp)),
|
||||
Err(e) => Err((StatusCode::BAD_GATEWAY, e)),
|
||||
}
|
||||
}
|
||||
|
||||
async fn rerank(
|
||||
State(client): State<AiClient>,
|
||||
Json(req): Json<RerankRequest>,
|
||||
) -> impl IntoResponse {
|
||||
tracing::info!("reranking {} documents", req.documents.len());
|
||||
match client.rerank(req).await {
|
||||
Ok(resp) => Ok(Json(resp)),
|
||||
Err(e) => Err((StatusCode::BAD_GATEWAY, e)),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user