mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
wip - trying to connect to OpenAi
This commit is contained in:
parent
e142647d8d
commit
5e26decf19
@ -625,7 +625,6 @@ public class ApplicationProperties {
|
||||
private String primary = "gpt-5-nano";
|
||||
private String fallback = "gpt-5-mini";
|
||||
private String embedding = "text-embedding-3-small";
|
||||
private String apiKey;
|
||||
}
|
||||
|
||||
@Data
|
||||
|
||||
@ -102,7 +102,6 @@ premium:
|
||||
primary: gpt-5-nano # Default lightweight model
|
||||
fallback: gpt-5-mini # Escalation model for complex prompts
|
||||
embedding: text-embedding-3-small # Embedding model for vector store usage
|
||||
apiKey: '' # Provide your OpenAI-compatible API key (or use SPRING_AI_OPENAI_API_KEY env var)
|
||||
rag:
|
||||
chunkSizeTokens: 512 # Token window used when chunking text
|
||||
chunkOverlapTokens: 128 # Overlap between successive chunks
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
package stirling.software.proprietary.config;
|
||||
|
||||
import org.springframework.ai.chat.model.ChatModel;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.openai.OpenAiChatModel;
|
||||
import org.springframework.ai.openai.OpenAiChatOptions;
|
||||
import org.springframework.ai.openai.OpenAiEmbeddingModel;
|
||||
import org.springframework.ai.openai.OpenAiEmbeddingOptions;
|
||||
import org.springframework.ai.openai.api.OpenAiApi;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import stirling.software.proprietary.service.chatbot.ChatbotFeatureProperties;
|
||||
import stirling.software.proprietary.service.chatbot.ChatbotFeatureProperties.ChatbotSettings;
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "premium.proFeatures.chatbot.enabled", havingValue = "true")
|
||||
public class ChatbotAiConfiguration {
|
||||
|
||||
@Bean
|
||||
public OpenAiApi chatbotOpenAiApi(ChatbotFeatureProperties properties) {
|
||||
ChatbotSettings settings = properties.current();
|
||||
String apiKey = settings.models().apiKey();
|
||||
if (!StringUtils.hasText(apiKey)) {
|
||||
throw new IllegalStateException(
|
||||
"premium.proFeatures.chatbot.models.apiKey must be set (or provide SPRING_AI_OPENAI_API_KEY)");
|
||||
}
|
||||
return new OpenAiApi(apiKey);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ChatModel chatbotChatModel(
|
||||
OpenAiApi chatbotOpenAiApi, ChatbotFeatureProperties properties) {
|
||||
OpenAiChatOptions options =
|
||||
OpenAiChatOptions.builder()
|
||||
.withModel(properties.current().models().primary())
|
||||
.build();
|
||||
return new OpenAiChatModel(chatbotOpenAiApi, options);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EmbeddingModel chatbotEmbeddingModel(
|
||||
OpenAiApi chatbotOpenAiApi, ChatbotFeatureProperties properties) {
|
||||
OpenAiEmbeddingOptions options =
|
||||
OpenAiEmbeddingOptions.builder()
|
||||
.withModel(properties.current().models().embedding())
|
||||
.build();
|
||||
return new OpenAiEmbeddingModel(chatbotOpenAiApi, options);
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ package stirling.software.proprietary.controller;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@ -34,6 +35,7 @@ import stirling.software.proprietary.service.chatbot.exception.ChatbotException;
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@ConditionalOnProperty(value = "premium.proFeatures.chatbot.enabled", havingValue = "true")
|
||||
@ConditionalOnBean(ChatbotService.class)
|
||||
public class ChatbotController {
|
||||
|
||||
private final ChatbotService chatbotService;
|
||||
|
||||
@ -3,6 +3,7 @@ package stirling.software.proprietary.controller;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@ -11,12 +12,14 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.proprietary.service.chatbot.ChatbotService;
|
||||
import stirling.software.proprietary.service.chatbot.exception.ChatbotException;
|
||||
import stirling.software.proprietary.service.chatbot.exception.NoTextDetectedException;
|
||||
|
||||
@RestControllerAdvice(assignableTypes = ChatbotController.class)
|
||||
@Slf4j
|
||||
@ConditionalOnProperty(value = "premium.proFeatures.chatbot.enabled", havingValue = "true")
|
||||
@ConditionalOnBean(ChatbotService.class)
|
||||
public class ChatbotExceptionHandler {
|
||||
|
||||
@ExceptionHandler(NoTextDetectedException.class)
|
||||
|
||||
@ -11,6 +11,7 @@ import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
|
||||
@ -16,6 +16,7 @@ import org.springframework.ai.chat.model.ChatResponse;
|
||||
import org.springframework.ai.chat.prompt.Prompt;
|
||||
import org.springframework.ai.openai.OpenAiChatModel;
|
||||
import org.springframework.ai.openai.OpenAiChatOptions;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
@ -38,6 +39,7 @@ import stirling.software.proprietary.service.chatbot.exception.ChatbotException;
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnProperty(value = "premium.proFeatures.chatbot.enabled", havingValue = "true")
|
||||
@ConditionalOnBean(ChatModel.class)
|
||||
public class ChatbotConversationService {
|
||||
|
||||
private final ChatModel chatModel;
|
||||
|
||||
@ -2,9 +2,7 @@ package stirling.software.proprietary.service.chatbot;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.model.ApplicationProperties.Premium;
|
||||
@ -15,23 +13,13 @@ import stirling.software.common.model.ApplicationProperties.Premium.ProFeatures.
|
||||
public class ChatbotFeatureProperties {
|
||||
|
||||
private final ApplicationProperties applicationProperties;
|
||||
private final Environment environment;
|
||||
|
||||
public ChatbotFeatureProperties(
|
||||
ApplicationProperties applicationProperties, Environment environment) {
|
||||
public ChatbotFeatureProperties(ApplicationProperties applicationProperties) {
|
||||
this.applicationProperties = applicationProperties;
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public ChatbotSettings current() {
|
||||
Chatbot chatbot = resolveChatbot();
|
||||
String configuredKey = Optional.ofNullable(chatbot.getModels().getApiKey()).orElse("");
|
||||
String fallbackKey = environment.getProperty("spring.ai.openai.api-key", "");
|
||||
String apiKey =
|
||||
StringUtils.hasText(configuredKey)
|
||||
? configuredKey
|
||||
: (StringUtils.hasText(fallbackKey) ? fallbackKey : "");
|
||||
|
||||
return new ChatbotSettings(
|
||||
chatbot.isEnabled(),
|
||||
chatbot.isAlphaWarning(),
|
||||
@ -40,8 +28,7 @@ public class ChatbotFeatureProperties {
|
||||
new ChatbotSettings.ModelSettings(
|
||||
chatbot.getModels().getPrimary(),
|
||||
chatbot.getModels().getFallback(),
|
||||
chatbot.getModels().getEmbedding(),
|
||||
apiKey),
|
||||
chatbot.getModels().getEmbedding()),
|
||||
new ChatbotSettings.RagSettings(
|
||||
chatbot.getRag().getChunkSizeTokens(),
|
||||
chatbot.getRag().getChunkOverlapTokens(),
|
||||
@ -77,8 +64,7 @@ public class ChatbotFeatureProperties {
|
||||
OcrSettings ocr,
|
||||
AuditSettings audit) {
|
||||
|
||||
public record ModelSettings(
|
||||
String primary, String fallback, String embedding, String apiKey) {}
|
||||
public record ModelSettings(String primary, String fallback, String embedding) {}
|
||||
|
||||
public record RagSettings(int chunkSizeTokens, int chunkOverlapTokens, int topK) {}
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import java.util.UUID;
|
||||
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.embedding.EmbeddingResponse;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
@ -24,6 +25,7 @@ import stirling.software.proprietary.service.chatbot.exception.NoTextDetectedExc
|
||||
|
||||
@Service
|
||||
@ConditionalOnProperty(value = "premium.proFeatures.chatbot.enabled", havingValue = "true")
|
||||
@ConditionalOnBean(EmbeddingModel.class)
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ChatbotIngestionService {
|
||||
|
||||
@ -7,6 +7,7 @@ import java.util.Optional;
|
||||
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.embedding.EmbeddingResponse;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@ -23,6 +24,7 @@ import stirling.software.proprietary.service.chatbot.exception.ChatbotException;
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@ConditionalOnProperty(value = "premium.proFeatures.chatbot.enabled", havingValue = "true")
|
||||
@ConditionalOnBean(EmbeddingModel.class)
|
||||
public class ChatbotRetrievalService {
|
||||
|
||||
private final ChatbotCacheService cacheService;
|
||||
|
||||
@ -3,6 +3,7 @@ package stirling.software.proprietary.service.chatbot;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -18,6 +19,7 @@ import stirling.software.proprietary.service.chatbot.exception.ChatbotException;
|
||||
|
||||
@Service
|
||||
@ConditionalOnProperty(value = "premium.proFeatures.chatbot.enabled", havingValue = "true")
|
||||
@ConditionalOnBean({ChatbotIngestionService.class, ChatbotConversationService.class})
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ChatbotService {
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
spring.ai.openai.enabled=true
|
||||
spring.ai.openai.api-key=your-proprietary-api-key-here
|
||||
@ -591,4 +591,4 @@ Remember, never hard-code text in your templates or Java code. Always use transl
|
||||
### Chatbot Feature Configuration
|
||||
|
||||
- The chatbot backend is disabled unless `premium.proFeatures.chatbot.enabled` is true in `configs/settings.yml`.
|
||||
- Provide an OpenAI-compatible key through `premium.proFeatures.chatbot.models.apiKey` (preferred) or the `SPRING_AI_OPENAI_API_KEY` environment variable. Without a key the app still boots, but the chatbot beans are not created.
|
||||
- Provide an OpenAI-compatible key via `SPRING_AI_OPENAI_API_KEY` (or `spring.ai.openai.api-key`) and set `spring.ai.openai.enabled=true` when you want chatbot beans to load. Leaving this property disabled allows the rest of Stirling-PDF to run without AI credentials.
|
||||
|
||||
@ -7,6 +7,9 @@ import { getApiBaseUrl } from '@app/services/apiClientConfig';
|
||||
const apiClient = axios.create({
|
||||
baseURL: getApiBaseUrl(),
|
||||
responseType: 'json',
|
||||
withCredentials: true,
|
||||
xsrfCookieName: 'XSRF-TOKEN',
|
||||
xsrfHeaderName: 'X-XSRF-TOKEN',
|
||||
});
|
||||
|
||||
// Setup interceptors (core does nothing, proprietary adds JWT auth)
|
||||
|
||||
@ -1,5 +1,21 @@
|
||||
import { AxiosInstance } from 'axios';
|
||||
|
||||
export function setupApiInterceptors(_client: AxiosInstance): void {
|
||||
// Core version: no interceptors to add
|
||||
function readXsrfToken(): string | undefined {
|
||||
const match = document.cookie
|
||||
.split(';')
|
||||
.map((cookie) => cookie.trim())
|
||||
.find((cookie) => cookie.startsWith('XSRF-TOKEN='));
|
||||
|
||||
return match ? decodeURIComponent(match.substring('XSRF-TOKEN='.length)) : undefined;
|
||||
}
|
||||
|
||||
export function setupApiInterceptors(client: AxiosInstance): void {
|
||||
client.interceptors.request.use((config) => {
|
||||
const token = readXsrfToken();
|
||||
if (token) {
|
||||
config.headers = config.headers ?? {};
|
||||
config.headers['X-XSRF-TOKEN'] = token;
|
||||
}
|
||||
return config;
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user