unique-web-search 1.8.1__tar.gz → 1.8.3__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.1 → unique_web_search-1.8.3}/PKG-INFO +2 -2
  2. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/pyproject.toml +2 -3
  3. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/config.py +10 -3
  4. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/executors/configs/__init__.py +1 -3
  5. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/executors/configs/v2_config.py +10 -3
  6. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/__init__.py +2 -2
  7. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/custom_api.py +11 -2
  8. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/settings.py +2 -0
  9. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/README.md +0 -0
  10. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/__init__.py +0 -0
  11. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/client_settings.py +0 -0
  12. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/prompts.py +0 -0
  13. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/schema.py +0 -0
  14. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/service.py +0 -0
  15. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/client/proxy_config.py +0 -0
  16. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/content_processing/__init__.py +0 -0
  17. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/content_processing/config.py +0 -0
  18. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/content_processing/service.py +0 -0
  19. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/crawlers/README.md +0 -0
  20. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/crawlers/__init__.py +0 -0
  21. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/crawlers/base.py +0 -0
  22. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/crawlers/basic.py +0 -0
  23. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/crawlers/crawl4ai.py +0 -0
  24. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/crawlers/firecrawl.py +0 -0
  25. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/crawlers/jina.py +0 -0
  26. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/crawlers/tavily.py +0 -0
  27. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/executors/README.md +0 -0
  28. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/executors/__init__.py +0 -0
  29. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/executors/base_executor.py +0 -0
  30. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/executors/configs/base.py +0 -0
  31. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/executors/configs/prompts.py +0 -0
  32. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/executors/configs/v1_config.py +0 -0
  33. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/executors/web_search_v1_executor.py +0 -0
  34. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/executors/web_search_v2_executor.py +0 -0
  35. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/helpers.py +0 -0
  36. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/README.md +0 -0
  37. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/base.py +0 -0
  38. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/bing.py +0 -0
  39. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/brave.py +0 -0
  40. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/firecrawl.py +0 -0
  41. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/google.py +0 -0
  42. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/jina.py +0 -0
  43. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/schema.py +0 -0
  44. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/tavily.py +0 -0
  45. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/utils/bing/__init__.py +0 -0
  46. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/utils/bing/identity.py +0 -0
  47. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/utils/bing/project.py +0 -0
  48. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/utils/google/schema.py +0 -0
  49. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/utils/vertexai/__init__.py +0 -0
  50. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/utils/vertexai/client.py +0 -0
  51. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/utils/vertexai/config.py +0 -0
  52. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/utils/vertexai/exceptions.py +0 -0
  53. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/utils/vertexai/gemini.py +0 -0
  54. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/utils/vertexai/prompts.py +0 -0
  55. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/utils/vertexai/response_handler.py +0 -0
  56. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/src/unique_web_search/services/search_engine/vertexai.py +0 -0
  57. {unique_web_search-1.8.1 → unique_web_search-1.8.3}/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.1
3
+ Version: 1.8.3
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.1"
3
+ version = "1.8.3"
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
-
@@ -1,7 +1,7 @@
1
1
  from logging import getLogger
2
- from typing import Annotated
2
+ from typing import Annotated, Literal
3
3
 
4
- from pydantic import BaseModel, Field, model_validator
4
+ from pydantic import BaseModel, Field, field_validator, model_validator
5
5
  from pydantic.json_schema import SkipJsonSchema
6
6
  from unique_toolkit._common.chunk_relevancy_sorter.config import (
7
7
  ChunkRelevancySortConfig,
@@ -109,7 +109,7 @@ class WebSearchConfig(BaseToolConfig):
109
109
  web_search_mode_config_v2: WebSearchV2Config = Field(
110
110
  default_factory=WebSearchV2Config,
111
111
  description="Web Search Mode Configuration V2",
112
- title="Web Search Mode Configuration V2 (Beta)",
112
+ title="Web Search Mode Configuration V2",
113
113
  )
114
114
 
115
115
  search_engine_config: ActivatedSearchEngine = Field( # type: ignore (This type is computed at runtime so pyright is not able to infer it)
@@ -188,3 +188,10 @@ class WebSearchConfig(BaseToolConfig):
188
188
  if self.web_search_active_mode == WebSearchMode.V1
189
189
  else self.web_search_mode_config_v2
190
190
  )
191
+
192
+ @field_validator("web_search_active_mode", mode="before")
193
+ @classmethod
194
+ def validate_web_search_active_mode(cls, v: str) -> Literal["v1", "v2"]:
195
+ if "v2" in v.lower(): # Make sure to handle "v2 (beta)" as well
196
+ return "v2"
197
+ return "v1"
@@ -19,9 +19,7 @@ def get_default_web_search_mode_config() -> WebSearchMode:
19
19
  case "v2":
20
20
  return WebSearchMode.V2
21
21
  case _:
22
- raise ValueError(
23
- f"Invalid web search mode: {env_settings.default_web_search_mode}"
24
- )
22
+ raise ValueError(f"Invalid web search mode: {env_settings.web_search_mode}")
25
23
 
26
24
 
27
25
  __all__ = [
@@ -1,6 +1,6 @@
1
1
  from typing import Annotated, Literal
2
2
 
3
- from pydantic import Field
3
+ from pydantic import Field, field_validator
4
4
  from pydantic.json_schema import SkipJsonSchema
5
5
  from unique_toolkit._common.pydantic.rjsf_tags import RJSFMetaTag
6
6
  from unique_toolkit.agentic.tools.config import get_configuration_dict
@@ -13,12 +13,12 @@ from unique_web_search.services.executors.configs.prompts import (
13
13
  DEFAULT_TOOL_DESCRIPTION,
14
14
  DEFAULT_TOOL_DESCRIPTION_FOR_SYSTEM_PROMPT,
15
15
  )
16
- from unique_web_search.services.helpers import beta_model_title_generator
16
+ from unique_web_search.services.helpers import clean_model_title_generator
17
17
 
18
18
 
19
19
  class WebSearchV2Config(BaseWebSearchModeConfig[WebSearchMode.V2]):
20
20
  model_config = get_configuration_dict(
21
- model_title_generator=beta_model_title_generator
21
+ model_title_generator=clean_model_title_generator
22
22
  )
23
23
  mode: SkipJsonSchema[Literal[WebSearchMode.V2]] = WebSearchMode.V2
24
24
 
@@ -46,3 +46,10 @@ class WebSearchV2Config(BaseWebSearchModeConfig[WebSearchMode.V2]):
46
46
  default=DEFAULT_TOOL_DESCRIPTION_FOR_SYSTEM_PROMPT["v2"],
47
47
  description="Description of the tool's capabilities, intended for inclusion in system prompts to inform the language model what the tool can do.",
48
48
  )
49
+
50
+ @field_validator("mode", mode="before")
51
+ @classmethod
52
+ def validate_mode(cls, v: str) -> Literal["v2"]:
53
+ if "v2" in v.lower(): # Make sure to handle "v2 (beta)" as well
54
+ return "v2"
55
+ raise ValueError(f"Invalid mode: {v}")
@@ -50,8 +50,8 @@ SearchEngineTypes = (
50
50
  | BingSearch
51
51
  | BraveSearch
52
52
  | FireCrawlSearch
53
- | VertexAIConfig
54
- | CustomAPIConfig
53
+ | VertexAI
54
+ | CustomAPI
55
55
  )
56
56
  SearchEngineConfigTypes = (
57
57
  GoogleConfig
@@ -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: