Skip to content

PR 3: Ollama Provider Protocol Conformance #4

Description

@gilmanb1

Overview

Update the existing OllamaCategorizationProvider to conform to the new LLMCategorizationProvider protocol. This preserves all existing Ollama functionality while enabling it to participate in the provider cascade.

Dependencies

Note: Can be developed in parallel with PR 2 (Apple Intelligence Provider).

Files to Modify

File Action Description
Sources/SortAI/Core/LLM/OllamaCategorizationProvider.swift Modify Add protocol conformance
Sources/SortAI/Core/LLM/OllamaModelManager.swift Minor updates Ensure compatibility

Implementation Details

1. Protocol Conformance

The existing Ollama provider needs these additions:

extension OllamaCategorizationProvider: LLMCategorizationProvider {
    var identifier: String { "ollama" }
    var priority: Int { 2 }  // After Apple Intelligence
    
    var supportsModelSelection: Bool { true }
    var supportsTemperature: Bool { true }
    var supportsCustomPrompts: Bool { true }
    
    func isAvailable() async -> Bool {
        // Use existing OllamaModelManager availability check
        return await modelManager.isServerAvailable()
    }
    
    func categorize(signature: FileSignature) async throws -> CategorizationResult {
        // Wrap existing categorization logic
        let response = try await performCategorization(signature)
        
        return CategorizationResult(
            categoryPath: response.categoryPath,
            confidence: response.confidence,
            rationale: response.rationale,
            extractedKeywords: response.keywords,
            provider: identifier,
            escalationThreshold: escalationThreshold
        )
    }
}

2. Preserve Existing Features

These existing features must continue to work:

  • Model fallback chain: deepseek-r1:8b → llama3.2 → llama3.1 → mistral → phi3
  • Auto-download missing models
  • Custom server URL configuration
  • Health monitoring with exponential backoff
  • Temperature and model selection

3. Response Mapping

Map existing Ollama response format to new CategorizationResult:

private func mapOllamaResponse(_ response: OllamaResponse) -> CategorizationResult {
    // Parse category path from Ollama's JSON response
    let categoryPath = CategoryPath(path: response.category)
    
    // Map confidence (Ollama often returns 0-100, normalize to 0-1)
    let normalizedConfidence = response.confidence > 1.0 
        ? response.confidence / 100.0 
        : response.confidence
    
    return CategorizationResult(
        categoryPath: categoryPath,
        confidence: normalizedConfidence,
        rationale: response.explanation ?? "Categorized by Ollama",
        extractedKeywords: response.keywords ?? [],
        provider: identifier,
        escalationThreshold: escalationThreshold
    )
}

Acceptance Criteria

  • Implements LLMCategorizationProvider protocol
  • All existing Ollama functionality preserved
  • Model fallback chain continues to work
  • Returns proper CategorizationResult with provider tracking
  • Existing tests continue to pass
  • No breaking changes to existing API

Testing

func testOllamaProtocolConformance() async {
    let provider = OllamaCategorizationProvider()
    
    XCTAssertEqual(provider.identifier, "ollama")
    XCTAssertEqual(provider.priority, 2)
    XCTAssertTrue(provider.supportsModelSelection)
    XCTAssertTrue(provider.supportsTemperature)
}

func testOllamaAvailabilityCheck() async {
    let provider = OllamaCategorizationProvider()
    let available = await provider.isAvailable()
    // Result depends on whether Ollama server is running
    XCTAssertNotNil(available)
}

func testOllamaCategorizationReturnsResult() async throws {
    // Only run if Ollama is available
    let provider = OllamaCategorizationProvider()
    guard await provider.isAvailable() else {
        throw XCTSkip("Ollama not available")
    }
    
    let signature = FileSignature.mock(filename: "test.pdf")
    let result = try await provider.categorize(signature: signature)
    
    XCTAssertEqual(result.provider, "ollama")
}

Backward Compatibility

This PR must maintain backward compatibility:

Feature Before After
Direct Ollama usage ✅ Works ✅ Still works
Model selection ✅ Works ✅ Still works
Server URL config ✅ Works ✅ Still works
Health checks ✅ Works ✅ Still works

Estimated Size

~50-100 lines of code (mostly protocol conformance additions)

Risk Assessment

Low - No functional changes, just interface adaptation. Existing tests serve as regression safety net.

Activity

  1. gilmanb1 commented on Jan 13, 2026

    @gilmanb1
    OwnerAuthor

    Dependencies: Blocked by #2

  2. gilmanb1 commented on Jan 13, 2026

    @gilmanb1
    OwnerAuthor

    ✅ Implementation Complete

    This feature was already implemented as part of the LLM_Research.md implementation. The code exists in the codebase and all 233 tests pass.

    A minor build fix was applied in commit 4341283 to fix the Apple Intelligence availability check API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    llm-providerLLM provider infrastructurephase-2Phase 2 - Parallel development

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions