From fde9d4ed47290cf726af6d26646b13ec322a9613 Mon Sep 17 00:00:00 2001 From: chyroc Date: Wed, 25 Dec 2024 17:36:29 +0800 Subject: [PATCH] docs: Add README explaining logid usage (#150) --- README.md | 25 +++++++++++++++++++++++++ cozepy/model.py | 28 ++++++++++++++++++---------- tests/test_chat.py | 22 +++++++++++----------- tests/test_workflows.py | 6 +++--- tests/test_workflows_chat.py | 14 +++++++------- 5 files changed, 64 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 46e0eb1..f72ca0b 100644 --- a/README.md +++ b/README.md @@ -659,6 +659,31 @@ coze = Coze(auth=TokenAuth(oauth_token.access_token)) oauth_token = device_oauth_app.refresh_access_token(oauth_token.refresh_token) ``` +### Debug + +The SDK support returning the logid of the request, which can be used to debug the request. +You can get the logid from the response of the request and submit it to the coze support team for further assistance. + +```python +import os +from cozepy import Coze, AsyncCoze, TokenAuth + +coze = Coze(auth=TokenAuth(os.getenv("COZE_API_TOKEN"))) + +bot = coze.bots.retrieve(bot_id='bot id') +print(bot.response.logid) # support for CozeModel + +stream = coze.chat.stream(bot_id='bot id', user_id='user id') +print(stream.response.logid) # support for stream + +workspaces = coze.workspaces.list() +print(workspaces.response.logid) # support for paged + +messages = coze.chat.messages.list(conversation_id='conversation id', chat_id='chat id') +print(messages.response.logid) # support for list(simple list, not paged) +``` + + ### Async usage cozepy supports asynchronous calls through `httpx.AsyncClient`. diff --git a/cozepy/model.py b/cozepy/model.py index 736fd72..82b03f5 100644 --- a/cozepy/model.py +++ b/cozepy/model.py @@ -583,7 +583,7 @@ def _check_has_more(self, has_more: Optional[bool] = None, last_id: Optional[str return False -class Stream(Generic[T], HTTPResponse): +class Stream(Generic[T]): def __init__( self, raw_response: httpx.Response, @@ -591,10 +591,14 @@ def __init__( fields: List[str], handler: Callable[[Dict[str, str], httpx.Response], T], ): - super().__init__(raw_response) self._iters = iters self._fields = fields self._handler = handler + self._raw_response = raw_response + + @property + def response(self) -> HTTPResponse: + return HTTPResponse(self._raw_response) def __iter__(self): return self @@ -611,7 +615,7 @@ def _extra_event(self) -> Dict[str, str]: if line == "": continue - log_debug("receive event, logid=%s, event=%s", self.logid, line) + log_debug("receive event, logid=%s, event=%s", self.response.logid, line) field, value = self._extra_field_data(line, data) data[field] = value @@ -624,11 +628,11 @@ def _extra_field_data(self, line: str, data: Dict[str, str]) -> Tuple[str, str]: if data[field] == "": return field, line[len(field) + 1 :].strip() else: - raise CozeInvalidEventError(field, line, self.logid) - raise CozeInvalidEventError("", line, self.logid) + raise CozeInvalidEventError(field, line, self.response.logid) + raise CozeInvalidEventError("", line, self.response.logid) -class AsyncStream(Generic[T], HTTPResponse): +class AsyncStream(Generic[T]): def __init__( self, iters: AsyncIterator[str], @@ -636,11 +640,15 @@ def __init__( handler: Callable[[Dict[str, str], httpx.Response], T], raw_response: httpx.Response, ): - super().__init__(raw_response) self._iters = iters self._fields = fields self._handler = handler self._iterator = self.__stream__() + self._raw_response = raw_response + + @property + def response(self) -> HTTPResponse: + return HTTPResponse(self._raw_response) async def __aiter__(self) -> AsyncIterator[T]: async for item in self._iterator: @@ -658,7 +666,7 @@ async def __stream__(self) -> AsyncIterator[T]: if line == "": continue - log_debug("async receive event, logid=%s, event=%s", self.logid, line) + log_debug("async receive event, logid=%s, event=%s", self.response.logid, line) field, value = self._extra_field_data(line, data) data[field] = value @@ -678,8 +686,8 @@ def _extra_field_data(self, line: str, data: Dict[str, str]) -> Tuple[str, str]: if data[field] == "": return field, line[len(field) + 1 :].strip() else: - raise CozeInvalidEventError(field, line, self.logid) - raise CozeInvalidEventError("", line, self.logid) + raise CozeInvalidEventError(field, line, self.response.logid) + raise CozeInvalidEventError("", line, self.response.logid) def _make_data(self): return dict(map(lambda x: (x, ""), self._fields)) diff --git a/tests/test_chat.py b/tests/test_chat.py index 54754d6..14a4137 100644 --- a/tests/test_chat.py +++ b/tests/test_chat.py @@ -170,7 +170,7 @@ def test_sync_chat_stream(self, respx_mock): stream = coze.chat.stream(bot_id="bot", user_id="user") assert stream - assert stream.logid == mock_logid + assert stream.response.logid == mock_logid events = list(stream) assert len(events) == 8 @@ -211,8 +211,8 @@ def test_sync_chat_audio_stream(self, respx_mock): ], ) assert stream - assert stream.logid is not None - assert stream.logid == mock_logid + assert stream.response.logid is not None + assert stream.response.logid == mock_logid events = list(stream) assert events @@ -229,8 +229,8 @@ def test_sync_chat_stream_error(self, respx_mock): mock_logid = mock_chat_stream(respx_mock, read_file("testdata/chat_error_resp.txt")) stream = coze.chat.stream(bot_id="bot", user_id="user") assert stream - assert stream.logid is not None - assert stream.logid == mock_logid + assert stream.response.logid is not None + assert stream.response.logid == mock_logid with pytest.raises(Exception, match="error event"): list(stream) @@ -241,8 +241,8 @@ def test_sync_chat_stream_failed(self, respx_mock): mock_logid = mock_chat_stream(respx_mock, read_file("testdata/chat_failed_resp.txt")) stream = coze.chat.stream(bot_id="bot", user_id="user") assert stream - assert stream.logid is not None - assert stream.logid == mock_logid + assert stream.response.logid is not None + assert stream.response.logid == mock_logid events = list(stream) assert events @@ -256,8 +256,8 @@ def test_sync_chat_stream_invalid_event(self, respx_mock): stream = coze.chat.stream(bot_id="bot", user_id="user") assert stream - assert stream.logid is not None - assert stream.logid == mock_logid + assert stream.response.logid is not None + assert stream.response.logid == mock_logid with pytest.raises(Exception, match="invalid chat.event: invalid"): list(stream) @@ -296,8 +296,8 @@ def test_sync_submit_tool_outputs_stream(self, respx_mock): conversation_id="conversation", chat_id="chat", tool_outputs=[], stream=True ) assert stream - assert stream.logid is not None - assert stream.logid == mock_logid + assert stream.response.logid is not None + assert stream.response.logid == mock_logid events = list(stream) assert events diff --git a/tests/test_workflows.py b/tests/test_workflows.py index dde4a36..e53f941 100644 --- a/tests/test_workflows.py +++ b/tests/test_workflows.py @@ -116,7 +116,7 @@ def test_sync_workflows_runs_stream(self, respx_mock): mock_logid = mock_create_workflows_runs_stream(respx_mock, read_file("testdata/workflow_run_stream_resp.txt")) stream = coze.workflows.runs.stream(workflow_id="id") - assert stream.logid == mock_logid + assert stream.response.logid == mock_logid events = list(stream) assert events assert len(events) == 9 @@ -131,7 +131,7 @@ def test_sync_workflows_runs_resume(self, respx_mock): resume_data="resume_data", interrupt_type=123, ) - assert stream.logid == mock_logid + assert stream.response.logid == mock_logid events = list(stream) assert events assert len(events) == 9 @@ -148,7 +148,7 @@ def test_sync_workflows_runs_invalid_stream_event(self, respx_mock): resume_data="resume_data", interrupt_type=123, ) - assert stream.logid == mock_logid + assert stream.response.logid == mock_logid with pytest.raises(Exception, match="invalid workflows.event: invalid"): list(stream) diff --git a/tests/test_workflows_chat.py b/tests/test_workflows_chat.py index 2bf0c83..5a87579 100644 --- a/tests/test_workflows_chat.py +++ b/tests/test_workflows_chat.py @@ -50,7 +50,7 @@ def test_sync_workflows_chat_stream(self, respx_mock): stream = coze.workflows.chat.stream(workflow_id="workflow", bot_id="bot") assert stream - assert stream.logid == mock_logid + assert stream.response.logid == mock_logid events = list(stream) assert len(events) == 8 @@ -80,8 +80,8 @@ def test_sync_chat_stream_error(self, respx_mock): mock_logid = mock_workflows_chat_stream(respx_mock, read_file("testdata/chat_error_resp.txt")) stream = coze.workflows.chat.stream(workflow_id="workflow", bot_id="bot") assert stream - assert stream.logid is not None - assert stream.logid == mock_logid + assert stream.response.logid is not None + assert stream.response.logid == mock_logid with pytest.raises(Exception, match="error event"): list(stream) @@ -92,8 +92,8 @@ def test_sync_chat_stream_failed(self, respx_mock): mock_logid = mock_workflows_chat_stream(respx_mock, read_file("testdata/chat_failed_resp.txt")) stream = coze.workflows.chat.stream(workflow_id="workflow", bot_id="bot") assert stream - assert stream.logid is not None - assert stream.logid == mock_logid + assert stream.response.logid is not None + assert stream.response.logid == mock_logid events = list(stream) assert events @@ -107,8 +107,8 @@ def test_sync_chat_stream_invalid_event(self, respx_mock): stream = coze.workflows.chat.stream(workflow_id="workflow", bot_id="bot") assert stream - assert stream.logid is not None - assert stream.logid == mock_logid + assert stream.response.logid is not None + assert stream.response.logid == mock_logid with pytest.raises(Exception, match="invalid chat.event: invalid"): list(stream)