relay-knowledge 1.1.17

Graph-database-based knowledge graph project.
Documentation
use std::time::Duration;

use super::*;
use crate::{
    domain::RerankMode,
    env::{EnvironmentConfig, PlatformKind, RELAY_KNOWLEDGE_TEXT_EMBEDDING_MODEL},
    retrieval::{EmbeddingProviderKind, ReadModelBackendMode},
};

#[test]
fn resolves_retrieval_read_model_runtime_from_environment() {
    let environment = EnvironmentConfig::from_pairs(
        PlatformKind::Unix,
        [
            ("RELAY_KNOWLEDGE_SEMANTIC_BACKEND", "external"),
            ("RELAY_KNOWLEDGE_VECTOR_BACKEND", "external"),
            ("RELAY_KNOWLEDGE_LLM_PROVIDER", "openai_compatible"),
            (
                "RELAY_KNOWLEDGE_EMBEDDING_BASE_URL",
                "https://embeddings.example/v1",
            ),
            ("RELAY_KNOWLEDGE_EMBEDDING_API_KEY", "secret-key"),
            ("RELAY_KNOWLEDGE_TEXT_EMBEDDING_MODEL", "text-embed-3-small"),
            ("RELAY_KNOWLEDGE_IMAGE_EMBEDDING_MODEL", "clip-vit-b32"),
            ("RELAY_KNOWLEDGE_EMBEDDING_DIMENSION", "1536"),
            ("RELAY_KNOWLEDGE_EMBEDDING_BATCH_SIZE", "16"),
            ("RELAY_KNOWLEDGE_EMBEDDING_TIMEOUT_MS", "9000"),
            ("RELAY_KNOWLEDGE_EMBEDDING_MAX_CONCURRENCY", "2"),
            ("RELAY_KNOWLEDGE_RERANK_BACKEND", "external"),
            ("RELAY_KNOWLEDGE_RERANK_MODEL", "bge-reranker-v2"),
            ("RELAY_KNOWLEDGE_RERANK_TIMEOUT_MS", "700"),
            ("RELAY_KNOWLEDGE_RERANK_CANDIDATE_MULTIPLIER", "5"),
            ("RELAY_KNOWLEDGE_RERANK_MAX_CANDIDATES", "80"),
        ],
    )
    .expect("environment should parse");

    let runtime = retrieval_config_from_environment(&environment.retrieval)
        .expect("retrieval runtime should compose");

    assert_eq!(runtime.semantic_mode, ReadModelBackendMode::External);
    assert_eq!(runtime.vector_mode, ReadModelBackendMode::External);
    assert_eq!(runtime.vector_model.name, "text-embed-3-small");
    assert_eq!(runtime.image_model.name, "clip-vit-b32");
    assert_eq!(runtime.vector_model.dimension, 1536);
    let remote = runtime
        .remote_embedding
        .expect("remote embedding config should be present");
    assert_eq!(remote.provider, EmbeddingProviderKind::OpenAiCompatible);
    assert_eq!(remote.redacted_base_url(), "https://embeddings.example");
    assert_eq!(remote.batch_size, 16);
    assert_eq!(remote.timeout, Duration::from_millis(9000));
    assert_eq!(remote.max_concurrency, 2);
    assert_eq!(runtime.rerank.mode, RerankMode::External);
    assert_eq!(runtime.rerank.model.as_deref(), Some("bge-reranker-v2"));
    assert_eq!(runtime.rerank.timeout, Duration::from_millis(700));
    assert_eq!(runtime.rerank.candidate_multiplier, 5);
    assert_eq!(runtime.rerank.max_candidates, 80);
}

#[test]
fn rejects_external_backend_without_remote_model_metadata() {
    let environment = EnvironmentConfig::from_pairs(
        PlatformKind::Unix,
        [
            ("RELAY_KNOWLEDGE_VECTOR_BACKEND", "external"),
            (
                "RELAY_KNOWLEDGE_EMBEDDING_BASE_URL",
                "https://embeddings.example/v1",
            ),
            ("RELAY_KNOWLEDGE_EMBEDDING_API_KEY", "secret-key"),
        ],
    )
    .expect("environment should parse");

    let error = retrieval_config_from_environment(&environment.retrieval)
        .expect_err("external backend should require explicit model metadata");

    assert_eq!(
        error,
        RetrievalRuntimeConfigError::MissingRemoteValue(RELAY_KNOWLEDGE_TEXT_EMBEDDING_MODEL)
    );
}

#[test]
fn rejects_blank_retrieval_model_overrides() {
    let environment = EnvironmentConfig::from_pairs(
        PlatformKind::Unix,
        [("RELAY_KNOWLEDGE_TEXT_EMBEDDING_MODEL", "   ")],
    )
    .expect("environment should parse");

    let error = retrieval_config_from_environment(&environment.retrieval)
        .expect_err("blank model name should fail");

    assert_eq!(
        error,
        RetrievalRuntimeConfigError::EmptyModelName(RELAY_KNOWLEDGE_TEXT_EMBEDDING_MODEL)
    );
}

#[test]
fn rejects_unknown_rerank_backend_mode() {
    let environment = EnvironmentConfig::from_pairs(
        PlatformKind::Unix,
        [("RELAY_KNOWLEDGE_RERANK_BACKEND", "remote")],
    )
    .expect("environment should parse");

    let error = retrieval_config_from_environment(&environment.retrieval)
        .expect_err("unknown rerank backend should fail");

    assert!(matches!(
        error,
        RetrievalRuntimeConfigError::InvalidRerankBackend(_)
    ));
}