Files
lm-lib/src/main/java/de/extio/lmlib/client/ClientService.java
extio-de 514dad1c7f feat: Introduce reasoning capabilities in chat and text completion
- Added AbstractCompletionRequest and AbstractCompletionResponse classes to standardize request and response structures.
- Implemented StreamOptions for streaming responses in chat completions.
- Enhanced ChatCompletionClient and TextCompletionClient to support reasoning content in responses.
- Updated ModelProfile to include reasoning effort and summary details.
- Created GptOssPromptStrategy to handle specific prompt formatting and reasoning extraction.
- Modified existing tests to validate reasoning content in completions.
- Updated configuration properties for reasoning settings in local properties files.
2025-10-01 19:05:15 +02:00

92 lines
3.3 KiB
Java
Executable File

package de.extio.lmlib.client;
import java.util.List;
import java.util.function.Consumer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import de.extio.lmlib.client.cached.CachedClient;
import de.extio.lmlib.client.cached.CachedClientRepository;
import de.extio.lmlib.profile.ModelCategory;
import de.extio.lmlib.profile.ModelProfile.ModelProvider;
import de.extio.lmlib.profile.ModelProfileService;
@Service
public class ClientService {
@Autowired
private List<Client> clients;
@Autowired
private ModelProfileService modelProfileService;
@Autowired(required = false)
private CachedClientRepository cachedClientRepository;
@Autowired(required = false)
private List<CompletionInterceptor> completionInterceptors;
@Cacheable("clients")
public Client getClient(final ModelCategory category) {
final var modelProfile = this.modelProfileService.getModelProfile(category.getModelProfile());
return this.clients.stream()
.filter(client -> client.getModelProvider() == modelProfile.modelProvider())
.findFirst()
.map(client -> this.cachedClientRepository == null ? client : new CachedClient(this.cachedClientRepository, this.modelProfileService, client))
.map(client -> this.completionInterceptors == null || this.completionInterceptors.isEmpty() ? client : new InterceptingClient(client, this.completionInterceptors))
.orElseThrow(() -> new IllegalStateException("No client found for model profile " + category));
}
private static class InterceptingClient implements Client {
private final Client client;
private final List<CompletionInterceptor> completionInterceptors;
public InterceptingClient(final Client client, final List<CompletionInterceptor> completionInterceptors) {
this.client = client;
this.completionInterceptors = completionInterceptors;
}
@Override
public Completion completion(final ModelCategory modelCategory, final String system, final String text) {
return this.client.completion(modelCategory, system, text);
}
@Override
public Completion conversation(final ModelCategory modelCategory, final Conversation conversation_) {
Conversation conversation = conversation_;
for (final var interceptor : this.completionInterceptors) {
conversation = interceptor.before(modelCategory, conversation);
}
var completion = this.client.conversation(modelCategory, conversation);
for (final var interceptor : this.completionInterceptors) {
completion = interceptor.after(modelCategory, completion);
}
return completion;
}
@Override
public Completion streamConversation(final ModelCategory modelCategory, final Conversation conversation_, final Consumer<Chunk> chunkConsumer) {
Conversation conversation = conversation_;
for (final var interceptor : this.completionInterceptors) {
conversation = interceptor.before(modelCategory, conversation);
}
var completion = this.client.streamConversation(modelCategory, conversation, chunkConsumer);
for (final var interceptor : this.completionInterceptors) {
completion = interceptor.after(modelCategory, completion);
}
return completion;
}
@Override
public ModelProvider getModelProvider() {
return this.client.getModelProvider();
}
}
}