1 /*
2 * Copyright 2012-2025 CodeLibs Project and the Others.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 * either express or implied. See the License for the specific language
14 * governing permissions and limitations under the License.
15 */
16 package org.codelibs.fess.llm;
17
18 import java.util.List;
19 import java.util.Map;
20
21 /**
22 * Interface for LLM (Large Language Model) clients.
23 * Implementations provide integration with different LLM providers
24 * such as Ollama, OpenAI, and Google Gemini.
25 *
26 * In addition to low-level chat operations, this interface defines
27 * high-level RAG workflow methods that allow each provider to optimize
28 * prompt construction, parameter tuning, and response parsing.
29 */
30 public interface LlmClient {
31
32 /**
33 * Performs a chat completion request.
34 *
35 * @param request the chat request containing messages and parameters
36 * @return the chat response from the LLM
37 * @throws LlmException if an error occurs during the request
38 */
39 LlmChatResponse chat(LlmChatRequest request);
40
41 /**
42 * Performs a streaming chat completion request.
43 * The callback is invoked for each chunk of the response.
44 *
45 * @param request the chat request containing messages and parameters
46 * @param callback the callback to receive streaming chunks
47 * @throws LlmException if an error occurs during the request
48 */
49 void streamChat(LlmChatRequest request, LlmStreamCallback callback);
50
51 /**
52 * Returns the name of this LLM client.
53 *
54 * @return the client name (e.g., "ollama", "openai", "gemini")
55 */
56 String getName();
57
58 /**
59 * Checks if this LLM client is available and properly configured.
60 *
61 * @return true if the client is available, false otherwise
62 */
63 boolean isAvailable();
64
65 // RAG workflow methods
66
67 /**
68 * Detects the intent of a user message.
69 *
70 * @param userMessage the user's message
71 * @return the detected intent with extracted keywords
72 */
73 IntentDetectionResult detectIntent(String userMessage);
74
75 /**
76 * Detects the intent of a user message with conversation history context.
77 *
78 * @param userMessage the user's message
79 * @param history the conversation history for context
80 * @return the detected intent with extracted keywords
81 */
82 default IntentDetectionResult detectIntent(String userMessage, List<LlmMessage> history) {
83 return detectIntent(userMessage);
84 }
85
86 /**
87 * Evaluates search results for relevance to the user's question.
88 *
89 * @param userMessage the original user message
90 * @param query the search query used
91 * @param searchResults the search results to evaluate
92 * @return evaluation result with relevant document IDs
93 */
94 RelevanceEvaluationResult evaluateResults(String userMessage, String query, List<Map<String, Object>> searchResults);
95
96 /**
97 * Generates an answer using document content (synchronous version for non-enhanced flow).
98 *
99 * @param userMessage the user's message
100 * @param documents the documents with content
101 * @param history the conversation history
102 * @return the chat response
103 */
104 LlmChatResponse generateAnswer(String userMessage, List<Map<String, Object>> documents, List<LlmMessage> history);
105
106 /**
107 * Regenerates a search query when the previous query failed to produce relevant results.
108 *
109 * @param userMessage the user's original message
110 * @param failedQuery the query that failed
111 * @param failureReason the reason for failure ("no_results" or "no_relevant_results")
112 * @param history the conversation history
113 * @return a new query string, or the userMessage if regeneration fails
114 */
115 String regenerateQuery(String userMessage, String failedQuery, String failureReason, List<LlmMessage> history);
116
117 /**
118 * Generates an answer using document content (streaming version for enhanced flow).
119 *
120 * @param userMessage the user's message
121 * @param documents the documents with content
122 * @param history the conversation history
123 * @param callback the streaming callback
124 */
125 void streamGenerateAnswer(String userMessage, List<Map<String, Object>> documents, List<LlmMessage> history,
126 LlmStreamCallback callback);
127
128 /**
129 * Generates a response asking user for clarification when intent is unclear.
130 *
131 * @param userMessage the user's message
132 * @param history the conversation history
133 * @param callback the streaming callback
134 */
135 void generateUnclearIntentResponse(String userMessage, List<LlmMessage> history, LlmStreamCallback callback);
136
137 /**
138 * Generates a response when no relevant documents are found.
139 *
140 * @param userMessage the user's message
141 * @param history the conversation history
142 * @param callback the streaming callback
143 */
144 void generateNoResultsResponse(String userMessage, List<LlmMessage> history, LlmStreamCallback callback);
145
146 /**
147 * Generates a response when the specified document URL is not found.
148 *
149 * @param userMessage the user's message
150 * @param documentUrl the URL that was not found
151 * @param history the conversation history
152 * @param callback the streaming callback
153 */
154 void generateDocumentNotFoundResponse(String userMessage, String documentUrl, List<LlmMessage> history, LlmStreamCallback callback);
155
156 /**
157 * Generates a summary of the specified documents.
158 *
159 * @param userMessage the user's message
160 * @param documents the documents to summarize
161 * @param history the conversation history
162 * @param callback the streaming callback
163 */
164 void generateSummaryResponse(String userMessage, List<Map<String, Object>> documents, List<LlmMessage> history,
165 LlmStreamCallback callback);
166
167 /**
168 * Generates an FAQ answer using document content (streaming).
169 * Uses a prompt optimized for direct, concise FAQ-style answers.
170 *
171 * @param userMessage the user's message
172 * @param documents the documents with content
173 * @param history the conversation history
174 * @param callback the streaming callback
175 */
176 void generateFaqAnswerResponse(String userMessage, List<Map<String, Object>> documents, List<LlmMessage> history,
177 LlmStreamCallback callback);
178
179 /**
180 * Generates a direct answer without document search.
181 *
182 * @param userMessage the user's message
183 * @param history the conversation history
184 * @param callback the streaming callback
185 */
186 void generateDirectAnswer(String userMessage, List<LlmMessage> history, LlmStreamCallback callback);
187
188 /**
189 * Gets the maximum characters for assistant message in history.
190 *
191 * @return the maximum characters
192 */
193 default int getHistoryAssistantMaxChars() {
194 return 800;
195 }
196
197 /**
198 * Gets the maximum characters for assistant summary in history.
199 *
200 * @return the maximum characters
201 */
202 default int getHistoryAssistantSummaryMaxChars() {
203 return 800;
204 }
205 }