Skip to content

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

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

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:

Problem:
ADK Java ships with built-in Gemini support and already offers the contrib/langchain4j bridge for wrapping third-party providers. However, the LangChain4j bridge requires explicit per-application wiring code: you must construct the provider object and pass a wrapper to .model(langChain4jWrapper). This approach does not use LlmRegistry and does not support model name strings — "groq/llama3" cannot be passed to .model("groq/...") without first calling LlmRegistry.registerLlm(...) somewhere in application startup. There is currently no convention-based, zero-code mechanism for classpath-driven provider discovery.

Solution:
Introduce a ServiceLoader SPI pattern (ModelProvider interface + ModelProviderRegistry) as a contrib module. Provider JARs self-register via META-INF/services — adding or removing a provider is a single Maven dependency change with zero application code modifications. A single call to ModelProviderRegistry.registerAll() in Runner or AdkWebServer.start() enables automatic discovery for all ADK applications.

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

Proposed ADK integration

  1. Three files from adk-model-prism-core would go into google-adk.jar
    • ModelProvider.java - public SPI interface
    • ModelProviderRegistry.java - ServiceLoader wiring
    • OpenAiCompatibleLlm.java - reusable base class for Open-AI-format APIs
  2. one line in Runner and AdkWebServer.start()
ModelProviderRegistry.registerAll(); // discovers all providers on the classpath

Provider JARs are published independently - no PRs to ADK core needed for new providers.

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