-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
perf: streaming response for DingTalk #4590
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| import asyncio | ||
| from typing import cast | ||
| from typing import Any, cast | ||
|
|
||
| import dingtalk_stream | ||
|
|
||
|
|
@@ -16,9 +16,11 @@ def __init__( | |
| platform_meta, | ||
| session_id, | ||
| client: dingtalk_stream.ChatbotHandler, | ||
| adapter: "Any" = None, | ||
| ): | ||
| super().__init__(message_str, message_obj, platform_meta, session_id) | ||
| self.client = client | ||
| self.adapter = adapter | ||
|
|
||
| async def send_with_client( | ||
| self, | ||
|
|
@@ -83,14 +85,58 @@ async def send(self, message: MessageChain): | |
| await super().send(message) | ||
|
|
||
| async def send_streaming(self, generator, use_fallback: bool = False): | ||
| buffer = None | ||
| async for chain in generator: | ||
| if not self.adapter or not self.adapter.card_template_id: | ||
| logger.warning( | ||
| f"DingTalk streaming is enabled, but 'card_template_id' is not configured for platform '{self.platform_meta.id}'. Falling back to text streaming." | ||
| ) | ||
| # Fallback to default behavior (buffer and send) | ||
| buffer = None | ||
| async for chain in generator: | ||
| if not buffer: | ||
| buffer = chain | ||
| else: | ||
| buffer.chain.extend(chain.chain) | ||
| if not buffer: | ||
| return None | ||
| buffer.squash_plain() | ||
| await self.send(buffer) | ||
| return await super().send_streaming(generator, use_fallback) | ||
|
|
||
| # Create card | ||
| msg_id = self.message_obj.message_id | ||
| incoming_msg = self.message_obj.raw_message | ||
| created = await self.adapter.create_message_card(msg_id, incoming_msg) | ||
|
|
||
| if not created: | ||
| # Fallback to default behavior (buffer and send) | ||
| buffer = None | ||
| async for chain in generator: | ||
| if not buffer: | ||
| buffer = chain | ||
| else: | ||
| buffer.chain.extend(chain.chain) | ||
| if not buffer: | ||
| buffer = chain | ||
| else: | ||
| buffer.chain.extend(chain.chain) | ||
| if not buffer: | ||
| return None | ||
| buffer.squash_plain() | ||
| await self.send(buffer) | ||
| return await super().send_streaming(generator, use_fallback) | ||
| return None | ||
| buffer.squash_plain() | ||
| await self.send(buffer) | ||
| return await super().send_streaming(generator, use_fallback) | ||
|
|
||
| full_content = "" | ||
| seq = 0 | ||
| try: | ||
| async for chain in generator: | ||
| for segment in chain.chain: | ||
| if isinstance(segment, Comp.Plain): | ||
| full_content += segment.text | ||
|
Comment on lines
+128
to
+130
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): 目前卡片流式发送中只包含 在这条流式处理路径中,只有 Original comment in Englishissue (bug_risk): Only In this streaming path, only |
||
|
|
||
| seq += 1 | ||
| if seq % 2 == 0: # Update every 2 chunks to be more responsive than 8 | ||
| await self.adapter.send_card_message( | ||
| msg_id, full_content, is_final=False | ||
| ) | ||
|
|
||
| await self.adapter.send_card_message(msg_id, full_content, is_final=True) | ||
| except Exception as e: | ||
| logger.error(f"DingTalk streaming error: {e}") | ||
| # Try to ensure final state is sent or cleaned up? | ||
| await self.adapter.send_card_message(msg_id, full_content, is_final=True) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): 建议将
send_streaming中共享的缓冲回退逻辑和卡片流式逻辑抽取为独立的辅助方法,以简化主方法的控制流并减少重复。你可以通过将通用的“缓冲并发送”路径和卡片流式逻辑抽取到几个小的辅助方法中,来降低
send_streaming的复杂度和重复度。这样既能保留当前所有行为,又能让控制流更清晰、更易维护。例如:
然后
send_streaming就可以简化为一个较短的调度方法:这样可以去除重复的缓冲逻辑,将卡片相关的细节隔离出来,并让
send_streaming专注于高层决策,同时不改变任何现有功能。Original comment in English
issue (complexity): Consider extracting the shared buffering fallback and card-streaming logic in
send_streaminginto separate helper methods to simplify the main method’s control flow and reduce duplication.You can reduce the complexity and duplication in
send_streamingby extracting the common “buffer and send” path and the card-streaming logic into small helpers. This keeps all current behavior but makes control flow clearer and easier to maintain.For example:
Then
send_streamingbecomes a short orchestration method:This removes the duplicated buffering logic, isolates the card-specific details, and keeps
send_streamingfocused on high-level decision-making without changing any functionality.