-
Notifications
You must be signed in to change notification settings - Fork 1
feat: implement structured chunk data structures and development security config #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,78 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package com.opencontext.config; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.context.annotation.Bean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.context.annotation.Configuration; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.core.env.Environment; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.security.config.http.SessionCreationPolicy; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.security.web.SecurityFilterChain; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.extern.slf4j.Slf4j; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Spring Security configuration for OpenContext API. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Implements API Key authentication for Admin APIs and allows unrestricted access | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * to MCP APIs and development endpoints. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Slf4j | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Configuration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @EnableWebSecurity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class SecurityConfig { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final Environment environment; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Bean | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info("Configuring Spring Security with profile-specific rules"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| http | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Disable CSRF for REST API | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .csrf(AbstractHttpConfigurer::disable) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Disable form login and basic auth | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .formLogin(AbstractHttpConfigurer::disable) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .httpBasic(AbstractHttpConfigurer::disable) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Stateless session management for REST API | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .sessionManagement(session -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Configure authorization rules | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .authorizeHttpRequests(authz -> authz | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Allow health check endpoints | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .requestMatchers("/actuator/health/**", "/actuator/info").permitAll() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Allow Swagger UI and API documentation (development) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .requestMatchers( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/swagger-ui/**", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/v3/api-docs/**", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/swagger-ui.html", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/swagger-resources/**", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/webjars/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ).permitAll() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Allow MCP API endpoints (no authentication required per PRD) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .requestMatchers("/api/v1/search/**", "/api/v1/get-content/**").permitAll() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Allow development mock data endpoints (development only) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .requestMatchers("/api/v1/dev/**").permitAll() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Admin APIs will require API Key authentication (TODO: implement in next step) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .requestMatchers("/api/v1/sources/**").permitAll() // Temporary - will add API key auth | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // All other requests require authentication | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .anyRequest().authenticated() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // TODO: Add API Key authentication filter for Admin APIs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // http.addFilterBefore(apiKeyAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info("Security configuration completed successfully"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return http.build(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | |
| .requestMatchers("/api/v1/sources/**").authenticated() // Require authentication (API key) | |
| // All other requests require authentication | |
| .anyRequest().authenticated() | |
| ); | |
| // Add API Key authentication filter for Admin APIs | |
| http.addFilterBefore(apiKeyAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); | |
| log.info("Security configuration completed successfully"); | |
| return http.build(); | |
| } | |
| /** | |
| * Simple API Key Authentication Filter for Admin APIs. | |
| * Checks for X-API-KEY header and authenticates if valid. | |
| */ | |
| private class ApiKeyAuthenticationFilter extends OncePerRequestFilter { | |
| private final AntPathRequestMatcher adminApiMatcher = new AntPathRequestMatcher("/api/v1/sources/**"); | |
| @Override | |
| protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) | |
| throws ServletException, IOException { | |
| if (adminApiMatcher.matches(request)) { | |
| String apiKey = request.getHeader(API_KEY_HEADER); | |
| if (ADMIN_API_KEY.equals(apiKey)) { | |
| Authentication auth = new PreAuthenticatedAuthenticationToken( | |
| "admin", apiKey, Collections.singletonList(new SimpleGrantedAuthority("ROLE_ADMIN"))); | |
| SecurityContextHolder.getContext().setAuthentication(auth); | |
| } else { | |
| response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); | |
| response.getWriter().write("Unauthorized: Invalid API Key"); | |
| return; | |
| } | |
| } | |
| filterChain.doFilter(request, response); | |
| } | |
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| package com.opencontext.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import jakarta.validation.constraints.PositiveOrZero; | ||
| import lombok.AccessLevel; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Hierarchical and contextual metadata for document chunks. | ||
| * Supports document structure navigation and search result organization. | ||
| */ | ||
| @Schema(description = "Hierarchical and contextual metadata for document chunks") | ||
| @Getter | ||
| @Builder | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| @AllArgsConstructor | ||
| public class ChunkMetadata { | ||
|
|
||
| /** | ||
| * Title or heading of this chunk. | ||
| * Used for displaying chunk context to users in search results. | ||
| */ | ||
| @Schema(description = "Title or heading of the chunk", example = "5.8.2. JWT Authentication Converter") | ||
| private String title; | ||
|
|
||
| /** | ||
| * Hierarchical breadcrumbs from document root to this chunk. | ||
| * Stored as array for flexibility in UI display and filtering. | ||
| * ES keyword type naturally supports arrays. | ||
| */ | ||
| @Schema(description = "Breadcrumb path from root to current chunk", | ||
| example = "[\"Chapter 5\", \"Security\", \"JWT\", \"Configuration\"]") | ||
| private List<String> breadcrumbs; | ||
|
|
||
| /** | ||
| * Depth level in document hierarchy (0 for root chunks). | ||
| * Used for hierarchy-aware search and display organization. | ||
| */ | ||
| @Schema(description = "Hierarchical depth level (0 for root)", example = "2") | ||
| @PositiveOrZero | ||
| private Integer hierarchyLevel; | ||
|
|
||
| /** | ||
| * Sequential order within document structure. | ||
| * Maintains original document flow for coherent retrieval. | ||
| */ | ||
| @Schema(description = "Sequential position in document", example = "15") | ||
| @PositiveOrZero | ||
| private Integer sequenceInDocument; | ||
|
|
||
| /** | ||
| * Document language for proper text processing. | ||
| * Currently supports Korean (ko) and English (en). | ||
| */ | ||
| @Schema(description = "Document language code", example = "ko") | ||
| private String language; | ||
|
|
||
| /** | ||
| * Source file type for context and processing hints. | ||
| */ | ||
| @Schema(description = "Source file type", example = "PDF") | ||
| private String fileType; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package com.opencontext.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import jakarta.validation.constraints.NotBlank; | ||
| import jakarta.validation.constraints.NotNull; | ||
| import lombok.AccessLevel; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| /** | ||
| * Response DTO for the get_content API endpoint. | ||
| * Provides complete chunk content with token information for LLM context management. | ||
| */ | ||
| @Schema(description = "Response for focused content retrieval (get_content)") | ||
| @Getter | ||
| @Builder | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| @AllArgsConstructor | ||
| public class GetContentResponse { | ||
|
|
||
| /** | ||
| * Complete text content of the requested chunk. | ||
| * May be truncated if exceeds maxTokens limit, but still returns 200 OK. | ||
| */ | ||
| @Schema(description = "Complete chunk content (may be token-limited)", | ||
| requiredMode = Schema.RequiredMode.REQUIRED) | ||
| @NotBlank | ||
| private String content; | ||
|
|
||
| /** | ||
| * Token processing information for LLM context management. | ||
| */ | ||
| @Schema(description = "Token processing information", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| @NotNull | ||
| private TokenInfo tokenInfo; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package com.opencontext.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import jakarta.validation.constraints.DecimalMax; | ||
| import jakarta.validation.constraints.DecimalMin; | ||
| import jakarta.validation.constraints.NotNull; | ||
| import lombok.AccessLevel; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| import java.util.List; | ||
| import java.util.UUID; | ||
|
|
||
| /** | ||
| * Individual search result item for exploratory knowledge discovery. | ||
| * Contains essential information for users to identify and select relevant chunks. | ||
| */ | ||
| @Schema(description = "Individual search result item for exploratory search (find_knowledge)") | ||
| @Getter | ||
| @Builder | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| @AllArgsConstructor | ||
| public class SearchResultItem { | ||
|
|
||
| /** | ||
| * Unique identifier of the chunk for subsequent get_content requests. | ||
| */ | ||
| @Schema(description = "Chunk identifier for content retrieval", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| @NotNull | ||
| private UUID chunkId; | ||
|
|
||
| /** | ||
| * Title or heading of the chunk for user context. | ||
| */ | ||
| @Schema(description = "Chunk title or heading", example = "5.8.2. JWT Authentication Converter") | ||
| private String title; | ||
|
|
||
| /** | ||
| * Content preview generated by extracting first 50 characters + "...". | ||
| * Following PRD specification for simple extraction over AI summarization. | ||
| */ | ||
| @Schema(description = "Content preview (first 50 chars + '...')", | ||
| example = "To customize the conversion from a JWT to an Auth...") | ||
| private String snippet; | ||
|
|
||
| /** | ||
| * Relevance score from hybrid search (BM25 + Vector similarity). | ||
| * Normalized to 0.0-1.0 range for consistent interpretation. | ||
| * Always present in search results. | ||
| */ | ||
| @Schema(description = "Search relevance score", example = "0.92", minimum = "0.0", maximum = "1.0") | ||
| @DecimalMin(value = "0.0") | ||
| @DecimalMax(value = "1.0") | ||
| @NotNull | ||
| private Double relevanceScore; | ||
|
|
||
| /** | ||
| * Hierarchical breadcrumbs for user navigation context. | ||
| * Helps users understand the chunk's position within document structure. | ||
| * Optional field that enhances UX when available. | ||
| */ | ||
| @Schema(description = "Breadcrumb path for navigation context", | ||
| example = "[\"Chapter 5\", \"Security\", \"JWT\", \"Configuration\"]") | ||
| private List<String> breadcrumbs; | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,71 @@ | ||||||||
| package com.opencontext.dto; | ||||||||
|
|
||||||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||||||
| import jakarta.validation.constraints.NotBlank; | ||||||||
| import jakarta.validation.constraints.NotNull; | ||||||||
| import lombok.AccessLevel; | ||||||||
| import lombok.AllArgsConstructor; | ||||||||
| import lombok.Builder; | ||||||||
| import lombok.Getter; | ||||||||
| import lombok.NoArgsConstructor; | ||||||||
|
|
||||||||
| import java.util.UUID; | ||||||||
|
|
||||||||
| /** | ||||||||
| * Structured document chunk for Elasticsearch indexing and storage. | ||||||||
| * Contains content, embeddings, and hierarchical metadata for semantic search. | ||||||||
| */ | ||||||||
| @Schema(description = "Elasticsearch document structure for structured chunks") | ||||||||
| @Getter | ||||||||
| @Builder | ||||||||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||||||||
| @AllArgsConstructor | ||||||||
| public class StructuredChunk { | ||||||||
|
|
||||||||
| /** | ||||||||
| * Unique identifier for the chunk, identical to PostgreSQL document_chunks.id. | ||||||||
| * This maintains data consistency between relational and search stores. | ||||||||
| */ | ||||||||
| @Schema(description = "Unique chunk identifier", requiredMode = Schema.RequiredMode.REQUIRED) | ||||||||
| @NotNull | ||||||||
| private UUID chunkId; | ||||||||
|
|
||||||||
| /** | ||||||||
| * UUID of the source document this chunk belongs to. | ||||||||
| * Used for filtering and document-level operations. | ||||||||
| */ | ||||||||
| @Schema(description = "Source document identifier", requiredMode = Schema.RequiredMode.REQUIRED) | ||||||||
| @NotNull | ||||||||
| private UUID sourceDocumentId; | ||||||||
|
|
||||||||
| /** | ||||||||
| * Original filename of the source document. | ||||||||
| * Provides context for users to identify document source. | ||||||||
| */ | ||||||||
| @Schema(description = "Original filename of source document", example = "spring-security-guide.pdf") | ||||||||
| private String originalFilename; | ||||||||
|
|
||||||||
| /** | ||||||||
| * The actual text content of this chunk. | ||||||||
| * This is the primary searchable content processed by Korean Nori analyzer. | ||||||||
| */ | ||||||||
| @Schema(description = "Text content of the chunk", requiredMode = Schema.RequiredMode.REQUIRED) | ||||||||
| @NotBlank | ||||||||
| private String content; | ||||||||
|
|
||||||||
| /** | ||||||||
| * 1024-dimensional embedding vector for semantic search. | ||||||||
| * Generated by Qwen3-Embedding-0.6B model via Ollama. | ||||||||
| * Uses float[] for optimal performance with Elasticsearch dense_vector type. | ||||||||
| */ | ||||||||
| @Schema(description = "Embedding vector for semantic search (1024 dimensions)") | ||||||||
|
||||||||
| @Schema(description = "Embedding vector for semantic search (1024 dimensions)") | |
| @Schema(description = "Embedding vector for semantic search (1024 dimensions)") | |
| @jakarta.validation.constraints.Size(min = 1024, max = 1024) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| package com.opencontext.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import jakarta.validation.constraints.NotBlank; | ||
| import jakarta.validation.constraints.PositiveOrZero; | ||
| import lombok.AccessLevel; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| /** | ||
| * Token processing information for LLM context management. | ||
| */ | ||
| @Schema(description = "Token processing information for LLM context management") | ||
| @Getter | ||
| @Builder | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| @AllArgsConstructor | ||
| public class TokenInfo { | ||
|
|
||
| /** | ||
| * Name of the tokenizer used for token counting. | ||
| * Currently fixed to tiktoken-cl100k_base but extensible for future LLM support. | ||
| */ | ||
| @Schema(description = "Tokenizer used for counting", example = "tiktoken-cl100k_base", | ||
| requiredMode = Schema.RequiredMode.REQUIRED) | ||
| @NotBlank | ||
| private String tokenizer; | ||
|
|
||
| /** | ||
| * Actual number of tokens in the returned content. | ||
| * May be less than original if content was truncated due to maxTokens limit. | ||
| * Can be 0 in extreme cases (empty content after processing). | ||
| */ | ||
| @Schema(description = "Actual token count of returned content", example = "7999", | ||
| requiredMode = Schema.RequiredMode.REQUIRED) | ||
| @PositiveOrZero | ||
| private Integer actualTokens; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import for
UsernamePasswordAuthenticationFilteris unused since the API key authentication filter is commented out. This unused import should be removed to maintain clean code.