unique-web-search 1.9.1__py3-none-any.whl → 1.10.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- unique_web_search/config.py +11 -2
- unique_web_search/service.py +95 -138
- unique_web_search/services/executors/__init__.py +12 -1
- unique_web_search/services/executors/base_executor.py +44 -59
- unique_web_search/services/executors/context.py +104 -0
- unique_web_search/services/executors/web_search_v1_executor.py +34 -77
- unique_web_search/services/executors/web_search_v2_executor.py +73 -83
- unique_web_search/services/message_log.py +70 -0
- unique_web_search/services/query_elicitation.py +162 -0
- unique_web_search/services/search_engine/vertexai.py +1 -1
- {unique_web_search-1.9.1.dist-info → unique_web_search-1.10.0.dist-info}/METADATA +1 -1
- {unique_web_search-1.9.1.dist-info → unique_web_search-1.10.0.dist-info}/RECORD +13 -10
- {unique_web_search-1.9.1.dist-info → unique_web_search-1.10.0.dist-info}/WHEEL +0 -0
unique_web_search/config.py
CHANGED
|
@@ -35,6 +35,7 @@ from unique_web_search.services.executors.configs import (
|
|
|
35
35
|
WebSearchV2Config,
|
|
36
36
|
get_default_web_search_mode_config,
|
|
37
37
|
)
|
|
38
|
+
from unique_web_search.services.query_elicitation import QueryElicitationConfig
|
|
38
39
|
from unique_web_search.services.search_engine import (
|
|
39
40
|
get_default_search_engine_config,
|
|
40
41
|
get_search_engine_config_types_from_names,
|
|
@@ -75,7 +76,11 @@ class AnswerGenerationConfig(BaseModel):
|
|
|
75
76
|
)
|
|
76
77
|
|
|
77
78
|
|
|
78
|
-
class ExperimentalFeatures(FeatureExtendedSourceSerialization):
|
|
79
|
+
class ExperimentalFeatures(FeatureExtendedSourceSerialization):
|
|
80
|
+
query_elicitation_config: QueryElicitationConfig = Field(
|
|
81
|
+
default_factory=QueryElicitationConfig,
|
|
82
|
+
description="Query elicitation configuration",
|
|
83
|
+
)
|
|
79
84
|
|
|
80
85
|
|
|
81
86
|
class WebSearchConfig(BaseToolConfig):
|
|
@@ -158,7 +163,11 @@ class WebSearchConfig(BaseToolConfig):
|
|
|
158
163
|
description="Tool format information for system prompt. This is used to format the tool response for the system prompt.",
|
|
159
164
|
)
|
|
160
165
|
|
|
161
|
-
experimental_features:
|
|
166
|
+
experimental_features: ExperimentalFeatures = Field(
|
|
167
|
+
default_factory=ExperimentalFeatures,
|
|
168
|
+
description="Experimental features",
|
|
169
|
+
title="Experimental Features",
|
|
170
|
+
)
|
|
162
171
|
|
|
163
172
|
debug: bool = Field(
|
|
164
173
|
default=False,
|
unique_web_search/service.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from time import time
|
|
2
3
|
|
|
3
4
|
from typing_extensions import override
|
|
@@ -10,31 +11,32 @@ from unique_toolkit.agentic.tools.tool import (
|
|
|
10
11
|
Tool,
|
|
11
12
|
)
|
|
12
13
|
from unique_toolkit.agentic.tools.tool_progress_reporter import ProgressState
|
|
13
|
-
from unique_toolkit.chat.schemas import (
|
|
14
|
-
MessageLog,
|
|
15
|
-
MessageLogDetails,
|
|
16
|
-
MessageLogEvent,
|
|
17
|
-
MessageLogStatus,
|
|
18
|
-
)
|
|
19
|
-
from unique_toolkit.content import ContentReference
|
|
20
14
|
from unique_toolkit.language_model.schemas import (
|
|
21
15
|
LanguageModelFunction,
|
|
22
16
|
LanguageModelToolDescription,
|
|
23
17
|
)
|
|
24
18
|
|
|
25
19
|
from unique_web_search.config import WebSearchConfig
|
|
26
|
-
from unique_web_search.schema import
|
|
20
|
+
from unique_web_search.schema import WebSearchPlan, WebSearchToolParameters
|
|
27
21
|
from unique_web_search.services.content_processing import ContentProcessor, WebPageChunk
|
|
28
22
|
from unique_web_search.services.crawlers import get_crawler_service
|
|
29
23
|
from unique_web_search.services.executors import (
|
|
30
24
|
WebSearchV1Executor,
|
|
31
25
|
WebSearchV2Executor,
|
|
32
26
|
)
|
|
33
|
-
from unique_web_search.services.executors.base_executor import WebSearchLogEntry
|
|
34
27
|
from unique_web_search.services.executors.configs import WebSearchMode
|
|
28
|
+
from unique_web_search.services.executors.context import (
|
|
29
|
+
ExecutorCallbacks,
|
|
30
|
+
ExecutorConfiguration,
|
|
31
|
+
ExecutorServiceContext,
|
|
32
|
+
)
|
|
33
|
+
from unique_web_search.services.message_log import WebSearchMessageLogger
|
|
34
|
+
from unique_web_search.services.query_elicitation import QueryElicitationService
|
|
35
35
|
from unique_web_search.services.search_engine import get_search_engine_service
|
|
36
36
|
from unique_web_search.utils import WebSearchDebugInfo, reduce_sources_to_token_limit
|
|
37
37
|
|
|
38
|
+
_LOGGER = logging.getLogger(__name__)
|
|
39
|
+
|
|
38
40
|
|
|
39
41
|
class WebSearchTool(Tool[WebSearchConfig]):
|
|
40
42
|
name = "WebSearch"
|
|
@@ -59,7 +61,6 @@ class WebSearchTool(Tool[WebSearchConfig]):
|
|
|
59
61
|
)
|
|
60
62
|
self.debug = self.config.debug
|
|
61
63
|
self._display_name = kwargs.get("display_name", "Web Search")
|
|
62
|
-
self._active_message_log: MessageLog | None = None
|
|
63
64
|
|
|
64
65
|
def content_reducer(web_page_chunks: list[WebPageChunk]) -> list[WebPageChunk]:
|
|
65
66
|
return reduce_sources_to_token_limit(
|
|
@@ -106,35 +107,37 @@ class WebSearchTool(Tool[WebSearchConfig]):
|
|
|
106
107
|
|
|
107
108
|
@override
|
|
108
109
|
async def run(self, tool_call: LanguageModelFunction) -> ToolCallResponse:
|
|
109
|
-
|
|
110
|
+
_LOGGER.info("Running the WebSearch tool")
|
|
110
111
|
start_time = time()
|
|
111
112
|
parameters = self.tool_parameter_calls.model_validate(
|
|
112
113
|
tool_call.arguments,
|
|
113
114
|
)
|
|
114
115
|
|
|
115
116
|
debug_info = WebSearchDebugInfo(parameters=parameters.model_dump())
|
|
116
|
-
|
|
117
|
+
|
|
118
|
+
web_search_message_logger = WebSearchMessageLogger(
|
|
119
|
+
message_step_logger=self._message_step_logger,
|
|
120
|
+
tool_display_name=self.display_name(),
|
|
121
|
+
)
|
|
122
|
+
executor = self._get_executor(
|
|
123
|
+
tool_call, parameters, debug_info, web_search_message_logger
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
notify_from_tool_call = self._ff_tool_progress_reporter_callback()
|
|
117
127
|
|
|
118
128
|
try:
|
|
119
|
-
content_chunks
|
|
129
|
+
content_chunks = await executor.run()
|
|
120
130
|
debug_info.num_chunks_in_final_prompts = len(content_chunks)
|
|
121
131
|
debug_info.execution_time = time() - start_time
|
|
122
132
|
|
|
123
|
-
|
|
124
|
-
queries_for_log=queries_for_log,
|
|
125
|
-
status=MessageLogStatus.COMPLETED,
|
|
126
|
-
)
|
|
133
|
+
await web_search_message_logger.finished()
|
|
127
134
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
name=executor.notify_name,
|
|
135
|
-
message=executor.notify_message,
|
|
136
|
-
state=ProgressState.FINISHED,
|
|
137
|
-
)
|
|
135
|
+
await notify_from_tool_call(
|
|
136
|
+
tool_call=tool_call,
|
|
137
|
+
name=executor.notify_name,
|
|
138
|
+
message=executor.notify_message,
|
|
139
|
+
state=ProgressState.FINISHED,
|
|
140
|
+
)
|
|
138
141
|
|
|
139
142
|
return ToolCallResponse(
|
|
140
143
|
id=tool_call.id, # type: ignore
|
|
@@ -143,22 +146,16 @@ class WebSearchTool(Tool[WebSearchConfig]):
|
|
|
143
146
|
content_chunks=content_chunks,
|
|
144
147
|
)
|
|
145
148
|
except Exception as e:
|
|
146
|
-
|
|
149
|
+
_LOGGER.exception(f"Error executing WebSearch tool: {e}")
|
|
147
150
|
|
|
148
|
-
|
|
149
|
-
status=MessageLogStatus.COMPLETED,
|
|
150
|
-
)
|
|
151
|
+
await web_search_message_logger.failed()
|
|
151
152
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
name=executor.notify_name,
|
|
159
|
-
message=executor.notify_message,
|
|
160
|
-
state=ProgressState.FAILED,
|
|
161
|
-
)
|
|
153
|
+
await notify_from_tool_call(
|
|
154
|
+
tool_call=tool_call,
|
|
155
|
+
name=executor.notify_name,
|
|
156
|
+
message=executor.notify_message,
|
|
157
|
+
state=ProgressState.FAILED,
|
|
158
|
+
)
|
|
162
159
|
|
|
163
160
|
return ToolCallResponse(
|
|
164
161
|
id=tool_call.id, # type: ignore
|
|
@@ -172,63 +169,59 @@ class WebSearchTool(Tool[WebSearchConfig]):
|
|
|
172
169
|
tool_call: LanguageModelFunction,
|
|
173
170
|
parameters: WebSearchPlan | WebSearchToolParameters,
|
|
174
171
|
debug_info: WebSearchDebugInfo,
|
|
172
|
+
web_search_message_logger: WebSearchMessageLogger,
|
|
175
173
|
) -> WebSearchV1Executor | WebSearchV2Executor:
|
|
176
|
-
#
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
174
|
+
# Initialize query elicitation service and get callbacks
|
|
175
|
+
elicitation_service = QueryElicitationService(
|
|
176
|
+
chat_service=self._chat_service,
|
|
177
|
+
display_name=self.display_name(),
|
|
178
|
+
config=self.config.experimental_features.query_elicitation_config,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# Build context objects
|
|
182
|
+
services = ExecutorServiceContext(
|
|
183
|
+
search_engine_service=self.search_engine_service,
|
|
184
|
+
crawler_service=self.crawler_service,
|
|
185
|
+
content_processor=self.content_processor,
|
|
186
|
+
language_model_service=self.language_model_service,
|
|
187
|
+
chunk_relevancy_sorter=self.chunk_relevancy_sorter,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
config = ExecutorConfiguration(
|
|
191
|
+
language_model=self.language_model,
|
|
192
|
+
chunk_relevancy_sort_config=self.config.chunk_relevancy_sort_config,
|
|
193
|
+
company_id=self.company_id,
|
|
194
|
+
debug_info=debug_info,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
callbacks = ExecutorCallbacks(
|
|
198
|
+
message_log_callback=web_search_message_logger,
|
|
199
|
+
content_reducer=self.content_reducer,
|
|
200
|
+
query_elicitation=elicitation_service,
|
|
201
|
+
tool_progress_reporter=self._ff_tool_progress_reporter(),
|
|
202
|
+
)
|
|
188
203
|
|
|
189
204
|
if isinstance(parameters, WebSearchPlan):
|
|
190
205
|
assert self.config.web_search_mode_config.mode == WebSearchMode.V2
|
|
191
206
|
return WebSearchV2Executor(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
crawler_service=self.crawler_service,
|
|
207
|
+
services=services,
|
|
208
|
+
config=config,
|
|
209
|
+
callbacks=callbacks,
|
|
196
210
|
tool_call=tool_call,
|
|
197
211
|
tool_parameters=parameters,
|
|
198
|
-
company_id=self.company_id,
|
|
199
|
-
content_processor=self.content_processor,
|
|
200
|
-
chunk_relevancy_sorter=self.chunk_relevancy_sorter,
|
|
201
|
-
chunk_relevancy_sort_config=self.config.chunk_relevancy_sort_config,
|
|
202
|
-
tool_progress_reporter=self.tool_progress_reporter
|
|
203
|
-
if not feature_flags.is_new_answers_ui_enabled(self.company_id)
|
|
204
|
-
else None,
|
|
205
|
-
content_reducer=self.content_reducer,
|
|
206
212
|
max_steps=self.config.web_search_mode_config.max_steps,
|
|
207
|
-
debug_info=debug_info,
|
|
208
|
-
message_log_callback=message_log_callback,
|
|
209
213
|
)
|
|
210
214
|
elif isinstance(parameters, WebSearchToolParameters):
|
|
211
215
|
assert self.config.web_search_mode_config.mode == WebSearchMode.V1
|
|
212
216
|
return WebSearchV1Executor(
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
crawler_service=self.crawler_service,
|
|
217
|
+
services=services,
|
|
218
|
+
config=config,
|
|
219
|
+
callbacks=callbacks,
|
|
217
220
|
tool_call=tool_call,
|
|
218
221
|
tool_parameters=parameters,
|
|
219
|
-
|
|
222
|
+
refine_query_system_prompt=self.config.web_search_mode_config.refine_query_mode.system_prompt,
|
|
220
223
|
mode=self.config.web_search_mode_config.refine_query_mode.mode,
|
|
221
224
|
max_queries=self.config.web_search_mode_config.max_queries,
|
|
222
|
-
content_processor=self.content_processor,
|
|
223
|
-
chunk_relevancy_sorter=self.chunk_relevancy_sorter,
|
|
224
|
-
chunk_relevancy_sort_config=self.config.chunk_relevancy_sort_config,
|
|
225
|
-
tool_progress_reporter=self.tool_progress_reporter
|
|
226
|
-
if not feature_flags.is_new_answers_ui_enabled(self.company_id)
|
|
227
|
-
else None,
|
|
228
|
-
content_reducer=self.content_reducer,
|
|
229
|
-
refine_query_system_prompt=self.config.web_search_mode_config.refine_query_mode.system_prompt,
|
|
230
|
-
debug_info=debug_info,
|
|
231
|
-
message_log_callback=message_log_callback,
|
|
232
225
|
)
|
|
233
226
|
else:
|
|
234
227
|
raise ValueError(f"Invalid parameters: {parameters}")
|
|
@@ -244,65 +237,29 @@ class WebSearchTool(Tool[WebSearchConfig]):
|
|
|
244
237
|
return []
|
|
245
238
|
return evaluation_check_list
|
|
246
239
|
|
|
247
|
-
def
|
|
248
|
-
self
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
data=[
|
|
263
|
-
MessageLogEvent(
|
|
264
|
-
type="WebSearch",
|
|
265
|
-
text=query_for_log.message,
|
|
240
|
+
def _ff_tool_progress_reporter(self):
|
|
241
|
+
if not feature_flags.enable_new_answers_ui_un_14411.is_enabled(self.company_id):
|
|
242
|
+
return self.tool_progress_reporter
|
|
243
|
+
return None
|
|
244
|
+
|
|
245
|
+
def _ff_tool_progress_reporter_callback(self):
|
|
246
|
+
async def notify_from_tool_call(
|
|
247
|
+
tool_call: LanguageModelFunction,
|
|
248
|
+
name: str,
|
|
249
|
+
message: str,
|
|
250
|
+
state: ProgressState,
|
|
251
|
+
):
|
|
252
|
+
if (
|
|
253
|
+
not feature_flags.enable_new_answers_ui_un_14411.is_enabled(
|
|
254
|
+
self.company_id
|
|
266
255
|
)
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
sequence_number = 0
|
|
272
|
-
for query_for_log in queries_for_log:
|
|
273
|
-
for web_search_result in query_for_log.web_search_results:
|
|
274
|
-
references.append(
|
|
275
|
-
web_search_result.to_content_reference(sequence_number)
|
|
256
|
+
and self.tool_progress_reporter is not None
|
|
257
|
+
):
|
|
258
|
+
await self.tool_progress_reporter.notify_from_tool_call(
|
|
259
|
+
tool_call, name, message, state
|
|
276
260
|
)
|
|
277
|
-
sequence_number += 1
|
|
278
|
-
|
|
279
|
-
return details, references
|
|
280
261
|
|
|
281
|
-
|
|
282
|
-
self,
|
|
283
|
-
*,
|
|
284
|
-
progress_message: str | None = None,
|
|
285
|
-
queries_for_log: list[WebSearchLogEntry] | list[str] | None = None,
|
|
286
|
-
status: MessageLogStatus | None = None,
|
|
287
|
-
) -> MessageLog | None:
|
|
288
|
-
details = MessageLogDetails(data=[])
|
|
289
|
-
reference_list = []
|
|
290
|
-
if queries_for_log is not None:
|
|
291
|
-
details, reference_list = self._prepare_message_logs_entries(
|
|
292
|
-
queries_for_log
|
|
293
|
-
)
|
|
294
|
-
|
|
295
|
-
self._active_message_log = (
|
|
296
|
-
self._message_step_logger.create_or_update_message_log(
|
|
297
|
-
active_message_log=self._active_message_log,
|
|
298
|
-
header=self._display_name,
|
|
299
|
-
progress_message=progress_message,
|
|
300
|
-
details=details,
|
|
301
|
-
references=reference_list,
|
|
302
|
-
**({"status": status} if status is not None else {}),
|
|
303
|
-
)
|
|
304
|
-
)
|
|
305
|
-
return self._active_message_log
|
|
262
|
+
return notify_from_tool_call
|
|
306
263
|
|
|
307
264
|
|
|
308
265
|
ToolFactory.register_tool(WebSearchTool, WebSearchConfig)
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
from unique_web_search.services.executors.context import (
|
|
2
|
+
ExecutorCallbacks,
|
|
3
|
+
ExecutorConfiguration,
|
|
4
|
+
ExecutorServiceContext,
|
|
5
|
+
)
|
|
1
6
|
from unique_web_search.services.executors.web_search_v1_executor import (
|
|
2
7
|
WebSearchV1Executor,
|
|
3
8
|
)
|
|
@@ -5,4 +10,10 @@ from unique_web_search.services.executors.web_search_v2_executor import (
|
|
|
5
10
|
WebSearchV2Executor,
|
|
6
11
|
)
|
|
7
12
|
|
|
8
|
-
__all__ = [
|
|
13
|
+
__all__ = [
|
|
14
|
+
"WebSearchV1Executor",
|
|
15
|
+
"WebSearchV2Executor",
|
|
16
|
+
"ExecutorServiceContext",
|
|
17
|
+
"ExecutorConfiguration",
|
|
18
|
+
"ExecutorCallbacks",
|
|
19
|
+
]
|
|
@@ -1,87 +1,65 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from abc import ABC, abstractmethod
|
|
3
3
|
from time import time
|
|
4
|
-
from typing import Callable, Optional, Protocol
|
|
5
4
|
|
|
6
|
-
from
|
|
7
|
-
from unique_toolkit import LanguageModelService
|
|
8
|
-
from unique_toolkit._common.chunk_relevancy_sorter.config import (
|
|
9
|
-
ChunkRelevancySortConfig,
|
|
10
|
-
)
|
|
11
|
-
from unique_toolkit._common.chunk_relevancy_sorter.service import ChunkRelevancySorter
|
|
12
|
-
from unique_toolkit._common.validators import LMI
|
|
5
|
+
from unique_toolkit.agentic.feature_flags import feature_flags
|
|
13
6
|
from unique_toolkit.agentic.tools.tool_progress_reporter import (
|
|
14
7
|
ProgressState,
|
|
15
|
-
ToolProgressReporter,
|
|
16
8
|
)
|
|
17
|
-
from unique_toolkit.chat.schemas import MessageLog, MessageLogStatus
|
|
18
9
|
from unique_toolkit.content import ContentChunk
|
|
19
10
|
from unique_toolkit.language_model import LanguageModelFunction
|
|
20
11
|
|
|
21
|
-
from unique_web_search.schema import
|
|
22
|
-
from unique_web_search.services.content_processing import
|
|
23
|
-
from unique_web_search.services.
|
|
24
|
-
|
|
12
|
+
from unique_web_search.schema import WebSearchPlan, WebSearchToolParameters
|
|
13
|
+
from unique_web_search.services.content_processing import WebPageChunk
|
|
14
|
+
from unique_web_search.services.executors.context import (
|
|
15
|
+
ExecutorCallbacks,
|
|
16
|
+
ExecutorConfiguration,
|
|
17
|
+
ExecutorServiceContext,
|
|
18
|
+
)
|
|
25
19
|
from unique_web_search.services.search_engine.schema import (
|
|
26
20
|
WebSearchResult,
|
|
27
21
|
)
|
|
28
|
-
from unique_web_search.utils import StepDebugInfo
|
|
22
|
+
from unique_web_search.utils import StepDebugInfo
|
|
29
23
|
|
|
30
24
|
_LOGGER = logging.getLogger(__name__)
|
|
31
25
|
|
|
32
26
|
|
|
33
|
-
class WebSearchLogEntry(BaseModel):
|
|
34
|
-
type: StepType
|
|
35
|
-
message: str
|
|
36
|
-
web_search_results: list[WebSearchResult]
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class MessageLogCallback(Protocol):
|
|
40
|
-
def __call__(
|
|
41
|
-
self,
|
|
42
|
-
*,
|
|
43
|
-
progress_message: str | None = None,
|
|
44
|
-
queries_for_log: list[WebSearchLogEntry] | list[str] | None = None,
|
|
45
|
-
status: MessageLogStatus | None = None,
|
|
46
|
-
) -> MessageLog | None: ...
|
|
47
|
-
|
|
48
|
-
|
|
49
27
|
class BaseWebSearchExecutor(ABC):
|
|
50
28
|
def __init__(
|
|
51
29
|
self,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
crawler_service: CrawlerTypes,
|
|
30
|
+
services: ExecutorServiceContext,
|
|
31
|
+
config: ExecutorConfiguration,
|
|
32
|
+
callbacks: ExecutorCallbacks,
|
|
56
33
|
tool_call: LanguageModelFunction,
|
|
57
34
|
tool_parameters: WebSearchPlan | WebSearchToolParameters,
|
|
58
|
-
company_id: str,
|
|
59
|
-
content_processor: ContentProcessor,
|
|
60
|
-
message_log_callback: MessageLogCallback,
|
|
61
|
-
chunk_relevancy_sorter: ChunkRelevancySorter | None,
|
|
62
|
-
chunk_relevancy_sort_config: ChunkRelevancySortConfig,
|
|
63
|
-
debug_info: WebSearchDebugInfo,
|
|
64
|
-
content_reducer: Callable[[list[WebPageChunk]], list[WebPageChunk]],
|
|
65
|
-
tool_progress_reporter: Optional[ToolProgressReporter] = None,
|
|
66
35
|
):
|
|
67
|
-
|
|
68
|
-
self.search_service =
|
|
69
|
-
self.crawler_service = crawler_service
|
|
70
|
-
self.
|
|
71
|
-
self.
|
|
72
|
-
self.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
self.
|
|
36
|
+
# Extract from service context
|
|
37
|
+
self.search_service = services.search_engine_service
|
|
38
|
+
self.crawler_service = services.crawler_service
|
|
39
|
+
self.content_processor = services.content_processor
|
|
40
|
+
self.language_model_service = services.language_model_service
|
|
41
|
+
self.chunk_relevancy_sorter = services.chunk_relevancy_sorter
|
|
42
|
+
|
|
43
|
+
# Extract from configuration
|
|
44
|
+
self.language_model = config.language_model
|
|
45
|
+
self.chunk_relevancy_sort_config = config.chunk_relevancy_sort_config
|
|
46
|
+
self.company_id = config.company_id
|
|
47
|
+
self.debug_info = config.debug_info
|
|
48
|
+
|
|
49
|
+
# Extract from callbacks
|
|
50
|
+
self._message_log_callback = callbacks.message_log_callback
|
|
51
|
+
self.content_reducer = callbacks.content_reducer
|
|
52
|
+
self.query_elicitation = callbacks.query_elicitation
|
|
53
|
+
self.tool_progress_reporter = callbacks.tool_progress_reporter
|
|
54
|
+
|
|
55
|
+
# Store tool parameters
|
|
76
56
|
self.tool_call = tool_call
|
|
77
57
|
self.tool_parameters = tool_parameters
|
|
78
|
-
|
|
58
|
+
|
|
59
|
+
# Initialize notification state
|
|
79
60
|
self._notify_name = ""
|
|
80
61
|
self._notify_message = ""
|
|
81
62
|
|
|
82
|
-
self.debug_info = debug_info
|
|
83
|
-
self._message_log_callback = message_log_callback
|
|
84
|
-
|
|
85
63
|
async def notify_callback() -> None:
|
|
86
64
|
_LOGGER.debug(f"{self.notify_name}: {self.notify_message}")
|
|
87
65
|
if self.tool_progress_reporter:
|
|
@@ -111,9 +89,7 @@ class BaseWebSearchExecutor(ABC):
|
|
|
111
89
|
self._notify_message = value
|
|
112
90
|
|
|
113
91
|
@abstractmethod
|
|
114
|
-
async def run(
|
|
115
|
-
self,
|
|
116
|
-
) -> tuple[list[ContentChunk], list[WebSearchLogEntry]]:
|
|
92
|
+
async def run(self) -> list[ContentChunk]:
|
|
117
93
|
raise NotImplementedError("Subclasses must implement this method.")
|
|
118
94
|
|
|
119
95
|
async def _content_processing(
|
|
@@ -167,3 +143,12 @@ class BaseWebSearchExecutor(ABC):
|
|
|
167
143
|
return sorted_chunks.content_chunks
|
|
168
144
|
else:
|
|
169
145
|
return content
|
|
146
|
+
|
|
147
|
+
async def _ff_elicitate_queries(self, queries: list[str]) -> list[str]:
|
|
148
|
+
if not feature_flags.enable_elicitation_un_15809.is_enabled(self.company_id):
|
|
149
|
+
return queries
|
|
150
|
+
|
|
151
|
+
# Create a query elicitation
|
|
152
|
+
elicitation = await self.query_elicitation(queries)
|
|
153
|
+
|
|
154
|
+
return elicitation
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""Context classes for executor dependency injection.
|
|
2
|
+
|
|
3
|
+
This module provides container classes that group related dependencies
|
|
4
|
+
for web search executors, reducing parameter redundancy in __init__ methods.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Optional, Protocol
|
|
9
|
+
|
|
10
|
+
from unique_toolkit import LanguageModelService
|
|
11
|
+
from unique_toolkit._common.chunk_relevancy_sorter.config import (
|
|
12
|
+
ChunkRelevancySortConfig,
|
|
13
|
+
)
|
|
14
|
+
from unique_toolkit._common.chunk_relevancy_sorter.service import ChunkRelevancySorter
|
|
15
|
+
from unique_toolkit._common.validators import LMI
|
|
16
|
+
from unique_toolkit.agentic.tools.tool_progress_reporter import (
|
|
17
|
+
ToolProgressReporter,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from unique_web_search.services.content_processing import ContentProcessor, WebPageChunk
|
|
21
|
+
from unique_web_search.services.crawlers import CrawlerTypes
|
|
22
|
+
from unique_web_search.services.search_engine import SearchEngineTypes
|
|
23
|
+
from unique_web_search.services.search_engine.schema import WebSearchResult
|
|
24
|
+
from unique_web_search.utils import WebSearchDebugInfo
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class ExecutorServiceContext:
|
|
29
|
+
"""Container for all service dependencies used by executors.
|
|
30
|
+
|
|
31
|
+
Groups together all the external services that executors depend on,
|
|
32
|
+
making it easier to pass dependencies and reducing parameter redundancy.
|
|
33
|
+
|
|
34
|
+
Attributes:
|
|
35
|
+
search_service: Service for performing web searches
|
|
36
|
+
crawler_service: Service for crawling and extracting web page content
|
|
37
|
+
content_processor: Service for processing and analyzing content
|
|
38
|
+
language_model_service: Service for language model operations
|
|
39
|
+
chunk_relevancy_sorter: Optional service for sorting content chunks by relevance
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
search_engine_service: SearchEngineTypes
|
|
43
|
+
crawler_service: CrawlerTypes
|
|
44
|
+
content_processor: ContentProcessor
|
|
45
|
+
language_model_service: LanguageModelService
|
|
46
|
+
chunk_relevancy_sorter: ChunkRelevancySorter | None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class ExecutorConfiguration:
|
|
51
|
+
"""Container for all configuration parameters used by executors.
|
|
52
|
+
|
|
53
|
+
Groups together all configuration values and metadata that executors need,
|
|
54
|
+
providing a clean separation between services and configuration.
|
|
55
|
+
|
|
56
|
+
Attributes:
|
|
57
|
+
language_model: Language model identifier and configuration
|
|
58
|
+
chunk_relevancy_sort_config: Configuration for chunk relevancy sorting
|
|
59
|
+
company_id: Identifier for the company/organization
|
|
60
|
+
debug_info: Container for debug information and metrics
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
language_model: LMI
|
|
64
|
+
chunk_relevancy_sort_config: ChunkRelevancySortConfig
|
|
65
|
+
company_id: str
|
|
66
|
+
debug_info: WebSearchDebugInfo
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ContentReducer(Protocol):
|
|
70
|
+
def __call__(self, web_page_chunks: list[WebPageChunk]) -> list[WebPageChunk]: ...
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class MessageLogCallback(Protocol):
|
|
74
|
+
async def log_progress(self, progress_message: str) -> None: ...
|
|
75
|
+
|
|
76
|
+
async def log_queries(self, queries: list[str]) -> None: ...
|
|
77
|
+
|
|
78
|
+
async def log_web_search_results(
|
|
79
|
+
self, web_search_results: list[WebSearchResult]
|
|
80
|
+
) -> None: ...
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class QueryElicitationProtocol(Protocol):
|
|
84
|
+
async def __call__(self, queries: list[str]) -> list[str]: ...
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class ExecutorCallbacks:
|
|
89
|
+
"""Container for callback functions used by executors.
|
|
90
|
+
|
|
91
|
+
Groups together all callback functions and optional reporters,
|
|
92
|
+
making the callback interface clear and extensible.
|
|
93
|
+
|
|
94
|
+
Attributes:
|
|
95
|
+
message_log_callback: Callback for logging messages and progress
|
|
96
|
+
content_reducer: Function to reduce content chunks based on token limits
|
|
97
|
+
query_elicitation: Function to elicit queries from the user
|
|
98
|
+
tool_progress_reporter: Optional reporter for tool execution progress
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
message_log_callback: MessageLogCallback
|
|
102
|
+
content_reducer: ContentReducer
|
|
103
|
+
query_elicitation: QueryElicitationProtocol
|
|
104
|
+
tool_progress_reporter: Optional[ToolProgressReporter] = None
|