Skip to content
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

fix(toolkit): Added missing chat_id in ContentService #139

Merged
merged 3 commits into from
Mar 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions unique_toolkit/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [0.7.2] - 2025-03-17
- HotFix `ContentService.search_content_chunks` to use `chat_id` from event if provided.

## [0.7.1] - 2025-03-11
- Fix Breaking change: `ContentService.search_content_chunks` `ContentService.search_content_chunks` now accepts`chat_id` for the specific to handle chat_only instances

Expand Down
2 changes: 1 addition & 1 deletion unique_toolkit/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "unique_toolkit"
version = "0.7.1"
version = "0.7.2"
description = ""
authors = [
"Martin Fadler <[email protected]>",
Expand Down
3 changes: 3 additions & 0 deletions unique_toolkit/tests/content/test_content_functions_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ def test_search_contents(mock_sdk, sample_content_data):
result = search_contents(
user_id="user123",
company_id="company123",
chat_id="chat123",
where={"key": "test.pdf"},
)

Expand All @@ -133,6 +134,7 @@ async def async_return():
result = await search_contents_async(
user_id="user123",
company_id="company123",
chat_id="chat123",
where={"key": "test.pdf"},
)

Expand Down Expand Up @@ -419,6 +421,7 @@ async def test_search_contents_async_error(mock_sdk):
await search_contents_async(
user_id="user123",
company_id="company123",
chat_id="chat123",
where={"key": "test.pdf"},
)
assert isinstance(exc_info.value, Exception)
Expand Down
24 changes: 13 additions & 11 deletions unique_toolkit/tests/content/test_content_service_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def setup(self):
)
self.service = ContentService(self.event)

@pytest.mark.unit
def test_search_content_chunks(self):
with patch.object(unique_sdk.Search, "create") as mock_create:
mock_create.return_value = [
Expand Down Expand Up @@ -69,7 +68,7 @@ def test_search_content_chunks(self):
mock_create.assert_called_once_with(
user_id="test_user",
company_id="test_company",
chatId="",
chatId="test_chat",
searchString="test",
searchType="COMBINED",
scopeIds=["scope1", "scope2"],
Expand Down Expand Up @@ -120,6 +119,7 @@ def test_search_contents(self):
mock_search.assert_called_once_with(
user_id="test_user",
company_id="test_company",
chatId="test_chat",
where={"key": "test_key"},
)

Expand Down Expand Up @@ -168,7 +168,7 @@ async def test_search_content_chunks_async(self):
mock_create.assert_called_once_with(
user_id="test_user",
company_id="test_company",
chatId="",
chatId="test_chat",
searchString="test",
searchType="COMBINED",
scopeIds=["scope1", "scope2"],
Expand Down Expand Up @@ -219,6 +219,7 @@ async def test_search_contents_async(self):

mock_search.assert_called_once_with(
user_id="test_user",
chatId="test_chat",
company_id="test_company",
where={"key": "test_key"},
)
Expand All @@ -236,6 +237,7 @@ async def test_error_handling_search_content_chunks_async(self):
def test_error_handling_incommensurate_use_of_chat_id_and_chat_only_sync(self):
with pytest.raises(ValueError):
# This should raise an exception due to invalid search type
self.service.chat_id = None
self.service.search_content_chunks(
search_string="test",
search_type=ContentSearchType.COMBINED,
Expand All @@ -248,6 +250,7 @@ def test_error_handling_incommensurate_use_of_chat_id_and_chat_only_sync(self):
async def test_error_handling_incommensurate_use_of_chat_id_and_chat_only_async(
self,
):
self.service.chat_id = None
with pytest.raises(ValueError):
# This should raise an exception due to invalid search type
await self.service.search_content_chunks_async(
Expand Down Expand Up @@ -560,6 +563,7 @@ def test_search_content_on_chat(self):
mock_search.assert_called_once_with(
user_id="test_user",
company_id="test_company",
chatId="chat_id",
where={"ownerId": {"equals": "chat_id"}},
)

Expand All @@ -583,7 +587,7 @@ def test_download_content_to_file_by_id(self, mock_get):
assert result.read_bytes() == b"Test content"

mock_get.assert_called_once_with(
f"{unique_sdk.api_base}/content/test_content_id/file",
f"{unique_sdk.api_base}/content/test_content_id/file?chatId=test_chat",
headers={
"x-api-version": unique_sdk.api_version,
"x-app-id": unique_sdk.app_id,
Expand Down Expand Up @@ -675,15 +679,13 @@ def test_request_content_by_id_without_chat_id(self, mock_get):
mock_response.content = b"Test content"
mock_get.return_value = mock_response

result = self.service.request_content_by_id(
content_id="test_content_id", chat_id=None
)
result = self.service.request_content_by_id(content_id="test_content_id")

assert result.status_code == 200
assert result.content == b"Test content"

mock_get.assert_called_once_with(
f"{unique_sdk.api_base}/content/test_content_id/file",
f"{unique_sdk.api_base}/content/test_content_id/file?chatId=test_chat",
headers={
"x-api-version": unique_sdk.api_version,
"x-app-id": unique_sdk.app_id,
Expand Down Expand Up @@ -713,7 +715,7 @@ def test_download_content_to_file_by_id_with_filename(self, mock_get):
assert result.read_bytes() == b"Test content"

mock_get.assert_called_once_with(
f"{unique_sdk.api_base}/content/test_content_id/file",
f"{unique_sdk.api_base}/content/test_content_id/file?chatId=test_chat",
headers={
"x-api-version": unique_sdk.api_version,
"x-app-id": unique_sdk.app_id,
Expand All @@ -734,7 +736,7 @@ def test_download_content_to_file_by_id_exception(self, mock_get):
self.service.download_content_to_file_by_id(content_id="test_content_id")

mock_get.assert_called_once_with(
f"{unique_sdk.api_base}/content/test_content_id/file",
f"{unique_sdk.api_base}/content/test_content_id/file?chatId=test_chat",
headers={
"x-api-version": unique_sdk.api_version,
"x-app-id": unique_sdk.app_id,
Expand Down Expand Up @@ -787,7 +789,7 @@ def test_init_with_direct_params(self):

assert service.company_id == "direct_company"
assert service.user_id == "direct_user"
assert not hasattr(service, "chat_id")
assert hasattr(service, "chat_id")
assert service.metadata_filter is None

def test_init_with_no_params(self):
Expand Down
4 changes: 4 additions & 0 deletions unique_toolkit/unique_toolkit/content/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ async def search_content_chunks_async(
def search_contents(
user_id: str,
company_id: str,
chat_id: str,
where: dict,
):
"""
Expand All @@ -151,6 +152,7 @@ def search_contents(
contents = unique_sdk.Content.search(
user_id=user_id,
company_id=company_id,
chatId=chat_id,
# TODO add type parameter in SDK
where=where, # type: ignore
)
Expand All @@ -163,6 +165,7 @@ def search_contents(
async def search_contents_async(
user_id: str,
company_id: str,
chat_id: str,
where: dict,
):
"""Asynchronously searches for content in the knowledge base."""
Expand All @@ -173,6 +176,7 @@ async def search_contents_async(
contents = await unique_sdk.Content.search_async(
user_id=user_id,
company_id=company_id,
chatId=chat_id,
where=where, # type: ignore
)
return map_contents(contents)
Expand Down
28 changes: 25 additions & 3 deletions unique_toolkit/unique_toolkit/content/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ContentService:
event: BaseEvent | Event, this can be None ONLY if company_id and user_id are provided.
company_id (str): The company ID.
user_id (str): The user ID.
chat_id (str): The chat ID. Defaults to None
metadata_filter (dict | None): is only initialised from an Event(Deprecated) or ChatEvent.
"""

Expand All @@ -46,6 +47,7 @@ def __init__(
event: Event | BaseEvent | None = None,
company_id: str | None = None,
user_id: str | None = None,
chat_id: str | None = None,
):
self._event = event # Changed to protected attribute
self.metadata_filter = None
Expand All @@ -54,10 +56,12 @@ def __init__(
self.user_id = event.user_id
if isinstance(event, (ChatEvent, Event)):
self.metadata_filter = event.payload.metadata_filter
self.chat_id = event.payload.chat_id
else:
[company_id, user_id] = validate_required_values([company_id, user_id])
self.company_id = company_id
self.user_id = user_id
self.chat_id = chat_id

@property
@deprecated(
Expand Down Expand Up @@ -110,6 +114,8 @@ def search_content_chunks(
if metadata_filter is None:
metadata_filter = self.metadata_filter

chat_id = chat_id or self.chat_id # type: ignore

if chat_only and not chat_id:
raise ValueError("Please provide chat_id when limiting with chat_only")

Expand Down Expand Up @@ -170,6 +176,8 @@ async def search_content_chunks_async(
if metadata_filter is None:
metadata_filter = self.metadata_filter

chat_id = chat_id or self.chat_id # type: ignore

if chat_only and not chat_id:
raise ValueError("Please provide chat_id when limiting with chat_only.")

Expand All @@ -196,6 +204,7 @@ async def search_content_chunks_async(
def search_contents(
self,
where: dict,
chat_id: str = "",
) -> list[Content]:
"""
Performs a search in the knowledge base by filter (and not a smilarity search)
Expand All @@ -207,15 +216,19 @@ def search_contents(
Returns:
list[Content]: The search results.
"""
chat_id = chat_id or self.chat_id # type: ignore

return search_contents(
user_id=self.user_id,
company_id=self.company_id,
chat_id=chat_id,
where=where,
)

async def search_contents_async(
self,
where: dict,
chat_id: str = "",
) -> list[Content]:
"""
Performs an asynchronous search for content files in the knowledge base by filter.
Expand All @@ -226,16 +239,19 @@ async def search_contents_async(
Returns:
list[Content]: The search results.
"""
chat_id = chat_id or self.chat_id # type: ignore

return await search_contents_async(
user_id=self.user_id,
company_id=self.company_id,
chat_id=chat_id,
where=where,
)

def search_content_on_chat(self, chat_id: str) -> list[Content]:
where = {"ownerId": {"equals": chat_id}}

return self.search_contents(where)
return self.search_contents(where, chat_id=chat_id)

def upload_content_from_bytes(
self,
Expand Down Expand Up @@ -310,7 +326,7 @@ def upload_content(
def request_content_by_id(
self,
content_id: str,
chat_id: str | None,
chat_id: str | None = None,
) -> Response:
"""
Sends a request to download content from a chat.
Expand All @@ -323,6 +339,8 @@ def request_content_by_id(
requests.Response: The response object containing the downloaded content.

"""
chat_id = chat_id or self.chat_id # type: ignore

return request_content_by_id(
user_id=self.user_id,
company_id=self.company_id,
Expand Down Expand Up @@ -353,6 +371,8 @@ def download_content_to_file_by_id(
Exception: If the download fails or the filename cannot be determined.
"""

chat_id = chat_id or self.chat_id # type: ignore

return download_content_to_file_by_id(
user_id=self.user_id,
company_id=self.company_id,
Expand Down Expand Up @@ -386,6 +406,8 @@ def download_content(
Exception: If the download fails.
"""

chat_id = chat_id or self.chat_id # type: ignore

return download_content(
user_id=self.user_id,
company_id=self.company_id,
Expand Down Expand Up @@ -413,7 +435,7 @@ def download_content_to_bytes(
Raises:
Exception: If the download fails.
"""

chat_id = chat_id or self.chat_id # type: ignore
return download_content_to_bytes(
user_id=self.user_id,
company_id=self.company_id,
Expand Down
Loading