Skip to content

feat:contrib/model-prism: pluggable LLM backend SPI for ADK Java via ServiceLoader#1199

Open
svetanis wants to merge 1 commit into
google:mainfrom
svetanis:feature/adk-model-prism
Open

feat:contrib/model-prism: pluggable LLM backend SPI for ADK Java via ServiceLoader#1199
svetanis wants to merge 1 commit into
google:mainfrom
svetanis:feature/adk-model-prism

Conversation

@svetanis
Copy link
Copy Markdown

@svetanis svetanis commented May 18, 2026

Add model-prism: pluggable LLM backend SPI for ADK Java via ServiceLoader

Please ensure you have read the contribution guide before creating a pull request.

Link to Issue or Description of Change

1. Related discussion:

2. Description of change:

This is a working prototype demonstrating one way to add pluggable LLM backends to ADK-Java via ServiceLoader.

Problem

Python ADK gets zero-code provider switching for free — dynamic imports and LiteLLM resolve a model string from config at runtime. This PR demonstrates the Java-idiomatic equivalent: a ServiceLoader-based SPI where a model string in config plus a Maven dependency swap is all it takes.

What goes where

Into google-adk.jar — SPI layer (3 files):

  • ModelProvider — SPI interface
  • ModelProviderRegistryServiceLoader wiring
  • OpenAiCompatibleLlm — reusable base class for any POST /v1/chat/completions provider

Into google-adk.jar — HTTP and serialization layer (or replaced by Google's existing implementation):

  • OpenAiHttpClient — HTTP client interface (default impl included; could be backed by ADK's existing ChatCompletionsHttpClient)
  • OpenAiMessageSerializer — serializer interface (default impl included; could be replaced by AdkChatSerializer using ADK 1.1.0 internal DTOs for richer response mapping)

Into Runner and AdkWebServer.start() (2 lines total):

ModelProviderRegistry.registerAll();

Everything else stays external. Provider JARs (Groq, Ollama, OpenRouter) live outside ADK and self-register via META-INF/services. No ADK PR is needed to add a new provider — dropping a JAR on the classpath in an ADK application is enough.

What's included

Module Purpose
model-prism-core ModelProvider SPI + OpenAiCompatibleLlm base class
model-prism-groq Groq provider (groq/.*)
model-prism-ollama Ollama provider — no API key, great for local dev
model-prism-openrouter OpenRouter provider — free tier available
model-prism-demo 11 runnable demos covering tools, streaming, web server

Tests

13 unit tests, all passing. See PR description for full list.

Manual E2E verified with Groq and Ollama.

Proposed core integration (one line)

// In Runner or AdkWebServer.start()
ModelProviderRegistry.registerAll();

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.
Tests run: 13, Failures: 0, Errors: 0, Skipped: 0

DefaultOpenAiMessageSerializerTest (9 tests):
  [OK] processStreamLines_textChunks_emitsPartialsThenFinal
  [OK] processStreamLines_emptyStream_emitsFinalEmptyResponse
  [OK] processStreamLines_nonDataLinesIgnored
  [OK] processStreamLines_toolCall_assemblesArgumentsAcrossChunks
  [OK] processStreamLines_multipleToolCalls_assemblesBothByIndex
  [OK] processStreamLines_errorChunk_throwsIllegalArgumentException
  [OK] processStreamLines_malformedJsonChunk_skippedGracefully
  [OK] deserializeResponse_textContent_returnsLlmResponseWithText
  [OK] deserializeResponse_toolCallContent_returnsFunctionCallPart

ModelProviderRegistryTest (4 tests):
  [OK] registerAll_singleProvider_registersPatternWithLlmRegistry
  [OK] registerAll_multipleProviders_registersAll
  [OK] registerAll_noProviders_returnsEmptyListAndNothingRegistered
  [OK] registerAll_calledTwice_registersEachTimeIndependently

Manual End-to-End (E2E) Tests:

The model-prism-demo module includes 11 runnable demo classes. To verify end-to-end:

# Set your key (OpenRouter has a free tier)
export OPENROUTER_API_KEY=your_key_here

# Basic SPI discovery
mvn -pl model-prism-demo exec:java -Dexec.mainClass=com.google.adk.models.demo.DemoApp

# Streaming
mvn -pl model-prism-demo exec:java -Dexec.mainClass=com.google.adk.models.demo.StreamingDemoApp

# Tool calling
mvn -pl model-prism-demo exec:java -Dexec.mainClass=com.google.adk.models.demo.tools.ToolsDemoApp

# ADK dev web server (open http://localhost:8080)
mvn -pl model-prism-demo exec:java -Dexec.mainClass=com.google.adk.models.demo.WebServerDemoApp

For Ollama (no API key required): install Ollama, run ollama pull llama3, then use model name ollama/llama3.

Checklist

  • I have read the CONTRIBUTING.md document.
  • My pull request contains a single commit.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

Additional context

Modules added under contrib/model-prism/:

Module Purpose
model-prism-core ModelProvider SPI, ModelProviderRegistry, OpenAiCompatibleLlm base class
model-prism-groq Groq provider (groq/.*)
model-prism-ollama Ollama provider (ollama/.*, no API key)
model-prism-openrouter OpenRouter provider (openrouter/.*, free tier available)
model-prism-demo 11 demo classes covering all major ADK features

@svetanis svetanis changed the title contrib/model-prism: pluggable LLM backend SPI for ADK Java via ServiceLoader contrib/model-prism: zero-config OpenAI-compatible provider discovery for ADK Java via ServiceLoader May 19, 2026
@svetanis svetanis changed the title contrib/model-prism: zero-config OpenAI-compatible provider discovery for ADK Java via ServiceLoader feat:contrib/model-prism: zero-config OpenAI-compatible provider discovery for ADK Java via ServiceLoader May 19, 2026
@svetanis svetanis changed the title feat:contrib/model-prism: zero-config OpenAI-compatible provider discovery for ADK Java via ServiceLoader feat:contrib/model-prism: pluggable LLM backend SPI for ADK Java via ServiceLoader May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant