agentscope-ai / agentscope-ai/agentscope-java

对AgentEvent解析的封装

Đang mở
#1,643 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
area/core/agent enhancement
Ngôn ngữ chính
Java
Star
5.6k
Fork
1.3k
Merge trung bình
4 ngày 12 giờ
Pull request đã merge (30 ngày)
77

Mô tả

v2.0.0-RC1的版本,没有找到对AgentEvent的解析封装。
python版本的Msg这个类提供了append_event这个方法,这点很方便人使用。

```python
def append_event(self, event: AgentEvent) -> Self:
"""Update the message by applying a streaming event.

Mutates ``self.content``, ``self.finished_at``, and ``self.usage``:
content blocks are appended/updated by block-level events,
``finished_at`` is stamped by ``REPLY_END``, and ``usage`` is
initialized then accumulated across each ``MODEL_CALL_END``.
Events whose ``reply_id`` does not match ``self.id`` are skipped with
a warning. Block-level delta/end events whose target block cannot be
found are also skipped with a warning.

Args:
event (`AgentEvent`):
The event to apply.
"""
from ..event import EventType # local import to avoid circular dep

if event.reply_id != self.id:
logger.warning(
"Event %s with reply_id %r does not match message id %r, "
"skipping.",
event.__class__.__name__,
event.reply_id,
self.id,
)
return self

match event.type:
case EventType.REPLY_END:
self.finished_at = event.created_at

case EventType.MODEL_CALL_END:
if self.usage is None:
self.usage = Usage(
input_tokens=event.input_tokens,
output_tokens=event.output_tokens,
)
else:
self.usage.input_tokens += event.input_tokens
self.usage.output_tokens += event.output_tokens

case EventType.TEXT_BLOCK_START:
self.content.append(TextBlock(id=event.block_id, text=""))

case EventType.TEXT_BLOCK_DELTA:
block = self._find_block("text", event.block_id)
if block is None:
logger.warning(
"TextBlock %r not found, skipping.",
event.block_id,
)
else:
block.text += event.delta

case EventType.TEXT_BLOCK_END:
pass

case EventType.DATA_BLOCK_START:
self.content.append(
DataBlock(
id=event.block_id,
source=Base64Source(
data="",
media_type=event.media_type,
),
),
)

case EventType.DATA_BLOCK_DELTA:
block = self._find_block("data", event.block_id)
if block is None:
logger.warning(
"DataBlock %s not found, skipping.",
event.block_id,
)
elif event.data:
block.source.data += event.data

case EventType.DATA_BLOCK_END:
pass

case EventType.THINKING_BLOCK_START:
self.content.append(
ThinkingBlock(id=event.block_id, thinking=""),
)

case EventType.THINKING_BLOCK_DELTA:
block = self._find_block("thinking", event.block_id)
if block is None:
logger.warning(
"ThinkingBlock %r not found, skipping.",
event.block_id,
)
else:
block.thinking += event.delta

case EventType.THINKING_BLOCK_END:
pass

case EventType.HINT_BLOCK:
# One-shot event — the full HintBlock content arrives in
# a single event, so just append it to ``content`` for
# persistence and replay.
self.content.append(
HintBlock(
id=event.block_id,
source=event.source,
hint=event.hint,
),
)

case EventType.TOOL_CALL_START:
self.content.append(
ToolCallBlock(
id=event.tool_call_id,
name=event.tool_call_name,
input="",
),
)

case EventType.TOOL_CALL_DELTA:
block = self._find_block("tool_call", event.tool_call_id)
if block is None:
logger.warning(
"ToolCallBlock %r not found, skipping.",
event.tool_call_id,
)
else:
assert isinstance(block, ToolCallBlock)
block.input += event.delta

case EventType.TOOL_CALL_END:
pass

case EventType.TOOL_RESULT_START:
self.content.append(
ToolResultBlock(
id=event.tool_call_id,
name=event.tool_call_name,
output=[],
state=ToolResultState.RUNNING,
),
)

case EventType.TOOL_RESULT_TEXT_DELTA:
block = self._find_block("tool_result", event.tool_call_id)
if block is None:
logger.warning(
"ToolResultBlock %r not found, skipping.",
event.tool_call_id,
)
else:
assert isinstance(block, ToolResultBlock)
if isinstance(block.output, str):
block.output = [TextBlock(text=block.output)]
# Append the text
if not block.output or block.output[-1].type != "text":
block.output.append(TextBlock(text=event.delta))
else:
block.output[-1].text += event.delta

case EventType.TOOL_RESULT_DATA_DELTA:
block = self._find_block("tool_result", event.tool_call_id)
if block is None:
logger.warning(
"ToolResultBlock %r not found, skipping.",
event.tool_call_id,
)
else:
assert isinstance(block, ToolResultBlock)
if isinstance(block.output, str):
block.output = [TextBlock(text=block.output)]
src = (
Base64Source(
data=event.data,
media_type=event.media_type,
)
if event.data is not None
else URLSource(
url=str(event.url),
media_type=event.media_type,
)
)
block.output.append(
DataBlock(id=event.block_id, source=src),
)

case EventType.TOOL_RESULT_END:
block = self._find_block("tool_result", event.tool_call_id)
if block is None:
logger.warning(
"ToolResultBlock %r not found, skipping.",
event.tool_call_id,
)
else:
assert isinstance(block, ToolResultBlock)
block.state = event.state
# The paired ToolCallBlock's lifecycle ends with its
# result — flip it to FINISHED here so the SSE-rebuilt
# reply_msg matches ``agent.state.context``, which
# ``_update_tool_call_state`` mutates directly.
call_block = self._find_block("tool_call", event.tool_call_id)
if call_block is not None:
assert isinstance(call_block, ToolCallBlock)
call_block.state = ToolCallState.FINISHED

case EventType.REQUIRE_USER_CONFIRM:
for tool_call in event.tool_calls:
b = self._find_block("tool_call", tool_call.id)
if b is not None:
assert isinstance(b, ToolCallBlock)
# Update the state
b.state = ToolCallState.ASKING
# Record the suggestions
b.suggested_rules = tool_call.suggested_rules

case EventType.USER_CONFIRM_RESULT:
for result in event.confirm_results:
b = self._find_block("tool_call", result.tool_call.id)
if b is not None:
assert isinstance(b, ToolCallBlock)
b.state = (
ToolCallState.ALLOWED
if result.confirmed
else ToolCallState.FINISHED
)

case EventType.REQUIRE_EXTERNAL_EXECUTION:
for tool_call in event.tool_calls:
b = self._find_block("tool_call", tool_call.id)
if b is not None:
assert isinstance(b, ToolCallBlock)
b.state = ToolCallState.SUBMITTED

case EventType.EXTERNAL_EXECUTION_RESULT:
for result in event.execution_results:
self.content.append(result)

return self
```

后面会出类似这种封装吗?还是说现在就有呢?

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.