Skip to content

#6040 - Improve LLM infrastructure#6105

Merged
reckart merged 5 commits into
mainfrom
refactoring/6040-Improve-LLM-infrastructure
Jul 12, 2026
Merged

#6040 - Improve LLM infrastructure#6105
reckart merged 5 commits into
mainfrom
refactoring/6040-Improve-LLM-infrastructure

Conversation

@reckart

@reckart reckart commented Jun 17, 2026

Copy link
Copy Markdown
Member

What's in the PR

  • Adds provider-neutral temperature / topP to ChatOptions and translates them in the Ollama/OpenAI/Azure adapters while preserving provider-specific overrides via the options bag.
  • Extends message/adapter plumbing to carry tool calls through conversation history (notably for Ollama) and updates the assistant loop to use the neutral client interfaces.
  • Makes the assistant’s chat and embedding endpoints/provider/auth configurable (top-level defaults + per-section overrides), updating wiring and tests accordingly.

How to test manually

  • Check if assistant still works

Automatic testing

  • PR includes unit tests

Documentation

  • PR updates documentation

@reckart reckart changed the title Refactoring/6040 improve llm infrastructure Issue #6040: Improve LLM infrastructure Jun 17, 2026
@reckart
reckart requested a review from Copilot June 17, 2026 20:42
@reckart reckart self-assigned this Jun 17, 2026
@reckart reckart added this to Kanban Jun 17, 2026
@github-project-automation github-project-automation Bot moved this to 🔖 To do in Kanban Jun 17, 2026
@reckart reckart added this to the 41.0 milestone Jun 17, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the assistant/LLM integration towards a provider-neutral infrastructure by introducing typed, cross-provider chat generation parameters and routing assistant chat/embedding through the LlmChatClient abstraction with configurable provider/URL/auth.

Changes:

  • Adds provider-neutral temperature / topP to ChatOptions and translates them in the Ollama/OpenAI/Azure adapters while preserving provider-specific overrides via the options bag.
  • Extends message/adapter plumbing to carry tool calls through conversation history (notably for Ollama) and updates the assistant loop to use the neutral client interfaces.
  • Makes the assistant’s chat and embedding endpoints/provider/auth configurable (top-level defaults + per-section overrides), updating wiring and tests accordingly.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
inception/inception-imls-ollama/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/llm/ollama/client/OllamaLlmChatClient.java Maps neutral chat options and tool calls onto Ollama request/response DTOs.
inception/inception-imls-llm-support/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/llm/client/ChatOptions.java Introduces typed temperature/topP, defensive copying, and a builder.
inception/inception-imls-llm-support/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/llm/ChatMessage.java Adds toolCalls to messages for round-tripping tool invocations in history.
inception/inception-imls-llm-support/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/llm/ChatBasedLlmRecommenderImplBase.java Switches to the new ChatOptions builder during exchanges.
inception/inception-imls-chatgpt/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/llm/chatgpt/client/ChatGptLlmChatClient.java Translates neutral temperature/topP into OpenAI request options.
inception/inception-imls-azureai-openai/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/llm/azureaiopenai/client/AzureAiOpenAiLlmChatClient.java Translates neutral temperature/topP into Azure OpenAI request options.
inception/inception-imls-azureai-openai/pom.xml Updates dependency-analyzer ignore configuration for slf4j false positives.
inception/inception-assistant/src/test/java/de/tudarmstadt/ukp/inception/assistant/AgentLoopTest.java Updates tests to use OllamaLlmChatClient instead of the raw Ollama client.
inception/inception-assistant/src/main/java/de/tudarmstadt/ukp/inception/assistant/embedding/EmbeddingServiceImpl.java Uses configurable embedding provider/URL/auth via the extension point.
inception/inception-assistant/src/main/java/de/tudarmstadt/ukp/inception/assistant/config/AssistantPropertiesImpl.java Adds provider/URL/API-key overrides for chat/embedding and chat options map.
inception/inception-assistant/src/main/java/de/tudarmstadt/ukp/inception/assistant/config/AssistantProperties.java Adds default + effective (resolved) provider/URL/API-key accessors.
inception/inception-assistant/src/main/java/de/tudarmstadt/ukp/inception/assistant/config/AssistantEmbeddingProperties.java Adds embedding provider/URL/API-key override getters.
inception/inception-assistant/src/main/java/de/tudarmstadt/ukp/inception/assistant/config/AssistantChatProperties.java Adds chat provider/URL/API-key override getters and a provider-specific options map.
inception/inception-assistant/src/main/java/de/tudarmstadt/ukp/inception/assistant/config/AssistantAutoConfiguration.java Wires LlmChatClientExtensionPoint into assistant service construction.
inception/inception-assistant/src/main/java/de/tudarmstadt/ukp/inception/assistant/AssistantServiceImpl.java Resolves the chat client by configured provider and updates agent construction.
inception/inception-assistant/src/main/java/de/tudarmstadt/ukp/inception/assistant/AgentLoop.java Migrates the loop to LlmChatClient + neutral message/options types and tool descriptors.
Comments suppressed due to low confidence (1)

inception/inception-assistant/src/main/java/de/tudarmstadt/ukp/inception/assistant/AgentLoop.java:309

  • firstTokenTime can remain 0 if the streaming callback never emits any chunks (e.g. a tool-call-only assistant turn with no content/thinking deltas). This makes delay negative and duration inflated in the performance metrics.
        // Send a final and complete message also including final metrics
        var responseMessageBuilder = newMessage(responseId) //
                .withContent(response.message().content()) //
                .withThinking(response.message().thinking()) //
                .withPerformance(MPerformanceMetrics.builder() //
                        .withDelay(firstTokenTime.get() - startTime) //
                        .withDuration(endTime - firstTokenTime.get()) //
                        .withTokens(tokens) //

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@reckart
reckart force-pushed the refactoring/6040-Improve-LLM-infrastructure branch from ae2a77a to 207d4e1 Compare June 22, 2026 20:29
@reckart reckart changed the title Issue #6040: Improve LLM infrastructure #6040 - Improve LLM infrastructure Jun 22, 2026
@reckart reckart modified the milestones: 41.0, 42.0 Jun 23, 2026
@reckart
reckart force-pushed the refactoring/6040-Improve-LLM-infrastructure branch from 207d4e1 to 3d055d4 Compare June 24, 2026 18:40
@reckart
reckart force-pushed the refactoring/6040-Improve-LLM-infrastructure branch 2 times, most recently from c91eebe to f7f0ede Compare July 12, 2026 17:09
reckart added 5 commits July 12, 2026 20:06
- Migrate the assistant's AgentLoop from the Ollama-specific OllamaClient to the provider-neutral LlmChatClient (chat, streaming, structured call, tool calling, usage, endpoint/auth)
- Resolve the chat client via LlmChatClientExtensionPoint in AssistantServiceImpl/AssistantAutoConfiguration (provider currently fixed to Ollama)
- Extend the shared ChatMessage with a toolCalls field so assistant tool-call turns survive in the conversation history
- Translate assistant tool-call turns (and thinking) onto the Ollama wire in OllamaLlmChatClient.toOllamaMessage
- Add a provider-specific options map (assistant.chat.options) as an escape hatch for generation knobs that have no provider-neutral equivalent; entries override the typed settings
- Update AgentLoopTest to drive the new LlmChatClient-based constructor (wrapping OllamaClientImpl in OllamaLlmChatClient)
- Drop the test scope from slf4j-api in inception-imls-azureai-openai so it is available at compile time
- Add provider-neutral temperature and topP fields (nullable Double, unset = use provider default) to ChatOptions
- Translate the neutral temperature/topP into each provider's own parameters in the Ollama, ChatGPT and Azure OpenAI adapters, with explicit options-bag entries overriding them
- Pass temperature/topP from the assistant as the neutral ChatOptions fields instead of Ollama-keyed entries in the option bag
- Add a builder to ChatOptions and use it in AgentLoop and ChatBasedLlmRecommenderImplBase
- Defensively copy tools and options into immutable collections in the ChatOptions compact constructor so the record cannot be mutated through a retained caller reference
- Configure maven-dependency-plugin in inception-imls-azureai-openai to ignore the analyze-only false positive for slf4j-api (kept at compile scope because it is needed transitively at compile time / by Eclipse)
- Add a top-level assistant.provider default plus per-section provider/url/api-key overrides under assistant.chat and assistant.embedding, so chat and embeddings can target different LLM providers/endpoints
- Add effective-setting resolver methods (getChatProvider/Url/ApiKey, getEmbeddingProvider/Url/ApiKey) on AssistantProperties that fall back from the section override to the top-level default
- Resolve the chat client by the effective chat provider id in AssistantServiceImpl instead of hardcoding Ollama, and build the chat endpoint from the effective chat url/api-key in AgentLoop
- Route the model-capability auto-detection to the effective chat url/api-key
- Resolve the embedding client/endpoint by the effective embedding provider/url and build authentication from the effective embedding api-key (previously always unauthenticated)
- Add LLM authentication infrastructure (LlmAuth interface/implementation) for API key management across providers
- Introduce ModelCapability enum and supportedCapabilities() API to declare backend features (STREAMING, TOOLS, CHAT, JSON_SCHEMA)
- Expand ChatOptions with neutral top-k, repeat-penalty, and context-length fields for provider-agnostic parameter handling
- Add ChatOptionsTranslator utility for mapping neutral ChatOptions to provider-specific parameters
- Add ModelDetails class for exposing model configuration and capabilities via LlmChatClient
- Implement chatStream() API across OpenAI and Azure adapters for streaming-first response handling
- Add tool-call support to OpenAI/Azure clients via ChatCompletionFunction, ChatCompletionTool, ChatCompletionToolCall, and ChatCompletionUsage classes
- Refactor ChatGptClientImpl and AzureAiOpenAiClientImpl to support both blocking and streaming chat operations with configurable stream callback
- Add ChatCompletionStreamOptions for controlling streaming behavior in OpenAI/Azure requests
- Enhance AgentLoop to check model capabilities before attempting tool calling or streaming, with graceful fallback
- Add LlmAuth apiKeyAuth() static import for standardized API key authentication across adapters
- Extend OllamaLlmChatClient to support streaming via chatStream() API
- Refactor ChatGptLlmChatClientTest and OllamaLlmChatClientTest to test streaming and non-streaming flows separately
- Add AgentLoopCapabilityGatingTest to verify tool calling and streaming are skipped when model capabilities are absent
- Reorganize test structure: rename OpenAiClientTest to AzureAiOpenAiClientIntegrationTest, add AzureAiOpenAiClientTest for unit tests
- Add ChatGptLlmChatClientIntegrationTest and OpenAiClientIntegrationTest for end-to-end OpenAI client scenarios
- Add AzureAiOpenAiLlmChatClientTest for unit testing Azure adapter
- Update AssistantAutoConfiguration to wire LlmAuth into the assistant module
- Update AssistantPropertiesImpl to support API key authentication configuration
- Refactor EmbeddingServiceImpl to use LlmAuth for standardized credential handling
- Update settings_assistant.adoc documentation to reflect new authentication and capability-based configuration
- Replace direct Option/JacksonOption references in AgentLoop with static imports for consistency
- Use a shared SSE parser for OpenAI and Azure providers
- Add reasoning/thinking effort support: new ReasoningEffort enum with model-default semantics, ChatOptions.reasoningEffort field, and adapter-specific mappings to OpenAI reasoning_effort and Ollama think levels
- Add tool_call_id tracking: MToolCall now includes an id field, threaded from wire protocol through AgentLoop to preserve OpenAI/Azure correlation semantics (Ollama uses positional matching)
- Implement JSON response sanitization: JsonResponseSanitizer utility to strip Markdown code fences from JSON mode responses (adapters now apply this conditionally based on ChatOptions.isJsonRequested())
- Fix Ollama thinking mode: change think field from hardcoded false to null=model-default, support level strings ("low"/"medium"/"high"/"max") for depth control alongside boolean true/false
- Add ChatOptions.isJsonRequested() helper to detect JSON-mode responses (jsonSchema supplied or responseFormat=JSON)
- Refactor OpenAI/Azure reasoning_effort handling: map ReasoningEffort.{MODEL_DEFAULT,NONE,MAX} to OpenAI's {null,"high"} space, null field = model default
- Add OllamazureContainer test fixture: testcontainers-based Ollama with Azure OpenAI client for live integration testing
- Split Ollama/Azure integration test scope: testcontainers dependency added to inception-testing as compile-scoped to support LLM test helpers
- Add new test classes: ChatCompletionMessageTest, AzureAiOpenAiClientLiveTest, AzureAiOpenAiLlmChatClientIntegrationTest
- Fix content trimming: non-streaming chat responses now trim surrounding whitespace (streaming path forwards raw deltas unchanged)
- Reorganize AgentLoop timing: set firstTokenTime=0 before non-streaming chat() call so duration attribution is correct
@reckart
reckart force-pushed the refactoring/6040-Improve-LLM-infrastructure branch from f7f0ede to 53973fa Compare July 12, 2026 18:14
@reckart
reckart merged commit 1eff3db into main Jul 12, 2026
4 checks passed
@reckart
reckart deleted the refactoring/6040-Improve-LLM-infrastructure branch July 12, 2026 18:41
@github-project-automation github-project-automation Bot moved this from 🔖 To do to 🍹 Done in Kanban Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: 🍹 Done

Development

Successfully merging this pull request may close these issues.

2 participants