unique-web-search 1.8.2__tar.gz → 1.9.0__tar.gz

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.
Files changed (57) hide show
  1. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/PKG-INFO +2 -2
  2. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/pyproject.toml +2 -3
  3. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/service.py +0 -1
  4. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/__init__.py +2 -4
  5. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/bing.py +16 -4
  6. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/custom_api.py +11 -2
  7. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/settings.py +2 -0
  8. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/README.md +0 -0
  9. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/__init__.py +0 -0
  10. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/client_settings.py +0 -0
  11. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/config.py +0 -0
  12. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/prompts.py +0 -0
  13. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/schema.py +0 -0
  14. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/client/proxy_config.py +0 -0
  15. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/content_processing/__init__.py +0 -0
  16. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/content_processing/config.py +0 -0
  17. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/content_processing/service.py +0 -0
  18. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/crawlers/README.md +0 -0
  19. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/crawlers/__init__.py +0 -0
  20. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/crawlers/base.py +0 -0
  21. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/crawlers/basic.py +0 -0
  22. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/crawlers/crawl4ai.py +0 -0
  23. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/crawlers/firecrawl.py +0 -0
  24. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/crawlers/jina.py +0 -0
  25. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/crawlers/tavily.py +0 -0
  26. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/executors/README.md +0 -0
  27. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/executors/__init__.py +0 -0
  28. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/executors/base_executor.py +0 -0
  29. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/executors/configs/__init__.py +0 -0
  30. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/executors/configs/base.py +0 -0
  31. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/executors/configs/prompts.py +0 -0
  32. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/executors/configs/v1_config.py +0 -0
  33. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/executors/configs/v2_config.py +0 -0
  34. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/executors/web_search_v1_executor.py +0 -0
  35. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/executors/web_search_v2_executor.py +0 -0
  36. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/helpers.py +0 -0
  37. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/README.md +0 -0
  38. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/base.py +0 -0
  39. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/brave.py +0 -0
  40. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/firecrawl.py +0 -0
  41. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/google.py +0 -0
  42. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/jina.py +0 -0
  43. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/schema.py +0 -0
  44. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/tavily.py +0 -0
  45. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/utils/bing/__init__.py +0 -0
  46. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/utils/bing/identity.py +0 -0
  47. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/utils/bing/project.py +0 -0
  48. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/utils/google/schema.py +0 -0
  49. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/utils/vertexai/__init__.py +0 -0
  50. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/utils/vertexai/client.py +0 -0
  51. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/utils/vertexai/config.py +0 -0
  52. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/utils/vertexai/exceptions.py +0 -0
  53. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/utils/vertexai/gemini.py +0 -0
  54. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/utils/vertexai/prompts.py +0 -0
  55. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/utils/vertexai/response_handler.py +0 -0
  56. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/services/search_engine/vertexai.py +0 -0
  57. {unique_web_search-1.8.2 → unique_web_search-1.9.0}/src/unique_web_search/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: unique-web-search
3
- Version: 1.8.2
3
+ Version: 1.9.0
4
4
  Summary:
5
5
  Author: Andreas Hauri, Gustav Hartz, Rami Azouz
6
6
  Author-email: Andreas Hauri <andreas@unique.ch>, Gustav Hartz <gustav.hartz.ext@unique.ch>, Rami Azouz <rami.ext@unique.ch>
@@ -17,7 +17,7 @@ Requires-Dist: tavily-python>=0.7.11,<1
17
17
  Requires-Dist: unidecode>=1.4.0,<2
18
18
  Requires-Dist: azure-ai-projects>=1.0.0,<2
19
19
  Requires-Dist: azure-identity>=1.25.0,<2
20
- Requires-Dist: unique-toolkit>=1.42.9,<2
20
+ Requires-Dist: unique-toolkit>=1.45.0,<2
21
21
  Requires-Dist: azure-core>=1.36.0,<2
22
22
  Requires-Dist: google-cloud-aiplatform>=1.128.0,<2
23
23
  Requires-Dist: google-auth>=2.43.0,<3
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "unique_web_search"
3
- version = "1.8.2"
3
+ version = "1.9.0"
4
4
  description = ""
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12,<4.0"
@@ -23,7 +23,7 @@ dependencies = [
23
23
  "unidecode>=1.4.0,<2",
24
24
  "azure-ai-projects>=1.0.0,<2",
25
25
  "azure-identity>=1.25.0,<2",
26
- "unique-toolkit>=1.42.9,<2",
26
+ "unique-toolkit>=1.45.0,<2",
27
27
  "azure-core>=1.36.0,<2",
28
28
  "google-cloud-aiplatform>=1.128.0,<2",
29
29
  "google-auth>=2.43.0,<3",
@@ -75,4 +75,3 @@ target-version = "py312"
75
75
 
76
76
  [tool.ruff.lint]
77
77
  extend-select = ["I"]
78
-
@@ -46,7 +46,6 @@ class WebSearchTool(Tool[WebSearchConfig]):
46
46
  self.search_engine_service = get_search_engine_service(
47
47
  self.config.search_engine_config,
48
48
  self.language_model_service,
49
- self.language_model,
50
49
  )
51
50
  self.crawler_service = get_crawler_service(self.config.crawler_config)
52
51
  self.chunk_relevancy_sorter = ChunkRelevancySorter(self.event)
@@ -3,7 +3,6 @@ from functools import reduce
3
3
  from typing import TypeAlias
4
4
 
5
5
  from unique_toolkit import LanguageModelService
6
- from unique_toolkit._common.validators import LMI
7
6
 
8
7
  from unique_web_search.services.search_engine.base import (
9
8
  BaseSearchEngineConfig,
@@ -79,7 +78,6 @@ ENGINE_NAME_TO_CONFIG = {
79
78
  def get_search_engine_service(
80
79
  search_engine_config: SearchEngineConfigTypes,
81
80
  language_model_service: LanguageModelService,
82
- lmi: LMI,
83
81
  ):
84
82
  match search_engine_config.search_engine_name:
85
83
  case SearchEngineType.FIRECRAWL:
@@ -91,9 +89,9 @@ def get_search_engine_service(
91
89
  case SearchEngineType.TAVILY:
92
90
  return TavilySearch(search_engine_config)
93
91
  case SearchEngineType.BING:
94
- return BingSearch(search_engine_config, language_model_service, lmi)
92
+ return BingSearch(search_engine_config, language_model_service)
95
93
  case SearchEngineType.BRAVE:
96
- return BraveSearch(search_engine_config, language_model_service, lmi)
94
+ return BraveSearch(search_engine_config)
97
95
  case SearchEngineType.VERTEXAI:
98
96
  return VertexAI(search_engine_config)
99
97
  case SearchEngineType.CUSTOM_API:
@@ -2,11 +2,13 @@ import logging
2
2
  from typing import Literal
3
3
 
4
4
  from azure.ai.agents.models import ListSortOrder
5
- from pydantic import BaseModel, Field
5
+ from pydantic import BaseModel, Field, field_validator
6
6
  from unique_toolkit import LanguageModelService
7
- from unique_toolkit._common.validators import LMI
7
+ from unique_toolkit._common.validators import LMI, get_LMI_default_field
8
8
  from unique_toolkit.agentic.tools.config import get_configuration_dict
9
9
  from unique_toolkit.language_model.builder import MessagesBuilder
10
+ from unique_toolkit.language_model.default_language_model import DEFAULT_GPT_4o
11
+ from unique_toolkit.language_model.infos import ModelCapabilities
10
12
 
11
13
  from unique_web_search.services.search_engine.base import (
12
14
  BaseSearchEngineConfig,
@@ -47,6 +49,17 @@ class BingSearchConfig(
47
49
  BaseSearchEngineConfig[SearchEngineType.BING], BingSearchOptionalQueryParams
48
50
  ):
49
51
  search_engine_name: Literal[SearchEngineType.BING] = SearchEngineType.BING
52
+ language_model: LMI = get_LMI_default_field(DEFAULT_GPT_4o)
53
+
54
+ @field_validator("language_model", mode="after")
55
+ @classmethod
56
+ def validate_language_model(cls, v: LMI) -> LMI:
57
+ if ModelCapabilities.STRUCTURED_OUTPUT not in v.capabilities:
58
+ raise ValueError(
59
+ f"Language model '{v.name}' does not support structured output. "
60
+ f"BingSearch requires a model with structured output capability."
61
+ )
62
+ return v
50
63
 
51
64
 
52
65
  class BingSearch(SearchEngine[BingSearchConfig]):
@@ -54,11 +67,10 @@ class BingSearch(SearchEngine[BingSearchConfig]):
54
67
  self,
55
68
  config: BingSearchConfig,
56
69
  language_model_service: LanguageModelService,
57
- lmi: LMI,
58
70
  ):
59
71
  super().__init__(config)
60
72
  self.language_model_service = language_model_service
61
- self.lmi = lmi
73
+ self.lmi = config.language_model
62
74
  self.credentials = get_crendentials()
63
75
  self.is_configured = credentials_are_valid(self.credentials)
64
76
 
@@ -1,5 +1,5 @@
1
1
  import json
2
- from typing import Literal, TypeVar
2
+ from typing import Any, Literal, TypeVar
3
3
 
4
4
  from httpx import AsyncClient
5
5
  from pydantic import Field
@@ -86,7 +86,10 @@ class CustomAPI(SearchEngine[CustomAPIConfig]):
86
86
  async def search(self, query: str, **kwargs) -> list[WebSearchResult]:
87
87
  params, body = self._prepare_request_params_and_body(query)
88
88
 
89
- async with AsyncClient(timeout=self.config.timeout) as client:
89
+ async_client_params = self._client_config | {
90
+ "timeout": self.config.timeout,
91
+ }
92
+ async with AsyncClient(**async_client_params) as client:
90
93
  response = await client.request(
91
94
  method=self._request_method,
92
95
  headers=self._headers,
@@ -118,6 +121,12 @@ class CustomAPI(SearchEngine[CustomAPIConfig]):
118
121
  def _additional_body_params(self) -> dict[str, str]:
119
122
  return json.loads(self.config.api_additional_body_params)
120
123
 
124
+ @property
125
+ def _client_config(self) -> dict[str, Any]:
126
+ if env_settings.custom_web_search_api_client_config is None:
127
+ return {}
128
+ return json.loads(env_settings.custom_web_search_api_client_config)
129
+
121
130
  def _prepare_request_params_and_body(self, query: str) -> tuple[dict, dict]:
122
131
  params = self._additional_query_params
123
132
  body = self._additional_body_params
@@ -66,6 +66,7 @@ class Base(BaseSettings):
66
66
  custom_web_search_api_headers: str | None = None
67
67
  custom_web_search_api_additional_query_params: str | None = None
68
68
  custom_web_search_api_additional_body_params: str | None = None
69
+ custom_web_search_api_client_config: str | None = None
69
70
 
70
71
  # Proxy settings
71
72
  ## Shared settings
@@ -139,6 +140,7 @@ class Base(BaseSettings):
139
140
  "custom_web_search_api_headers",
140
141
  "custom_web_search_api_additional_query_params",
141
142
  "custom_web_search_api_additional_body_params",
143
+ "custom_web_search_api_client_config",
142
144
  mode="after",
143
145
  )
144
146
  def validate_json(cls, v: str | None, info: ValidationInfo) -> str | None: