mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-30 14:17:14 +00:00
fix(longtext): avoid split interfering with multi-chain agent responses
Use query variable '_longtext_split_extra_chains' to pass extra split segments instead of appending to resp_message_chain directly. This prevents agent tool-call multi-round responses from being misidentified as split results and sent repeatedly. respback.py reverts to original single-chain logic and appends split extra chains after the main response.
This commit is contained in:
@@ -97,10 +97,15 @@ class LongTextProcessStage(stage.PipelineStage):
|
|||||||
original_text = str(query.resp_message_chain[-1])
|
original_text = str(query.resp_message_chain[-1])
|
||||||
threshold = query.pipeline_config['output']['long-text-processing']['threshold']
|
threshold = query.pipeline_config['output']['long-text-processing']['threshold']
|
||||||
segments = self.strategy_impl.split_text(original_text, threshold)
|
segments = self.strategy_impl.split_text(original_text, threshold)
|
||||||
query.resp_message_chain.pop()
|
# Replace the last chain with the first segment, store extra segments separately
|
||||||
for segment in segments:
|
# to avoid interfering with existing multi-chain scenarios (e.g. agent tool calls)
|
||||||
query.resp_message_chain.append(
|
query.resp_message_chain[-1] = platform_message.MessageChain(
|
||||||
platform_message.MessageChain([platform_message.Plain(text=segment)])
|
[platform_message.Plain(text=segments[0])]
|
||||||
|
)
|
||||||
|
if len(segments) > 1:
|
||||||
|
query.set_variable(
|
||||||
|
'_longtext_split_extra_chains',
|
||||||
|
[platform_message.MessageChain([platform_message.Plain(text=seg)]) for seg in segments[1:]],
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
query.resp_message_chain[-1] = platform_message.MessageChain(
|
query.resp_message_chain[-1] = platform_message.MessageChain(
|
||||||
|
|||||||
@@ -30,48 +30,40 @@ class SendResponseBackStage(stage.PipelineStage):
|
|||||||
|
|
||||||
await asyncio.sleep(random_delay)
|
await asyncio.sleep(random_delay)
|
||||||
|
|
||||||
|
if query.pipeline_config['output']['misc']['at-sender'] and isinstance(
|
||||||
|
query.message_event, platform_events.GroupMessage
|
||||||
|
):
|
||||||
|
query.resp_message_chain[-1].insert(0, platform_message.At(target=query.message_event.sender.id))
|
||||||
|
|
||||||
quote_origin = query.pipeline_config['output']['misc']['quote-origin']
|
quote_origin = query.pipeline_config['output']['misc']['quote-origin']
|
||||||
|
|
||||||
if len(query.resp_message_chain) > 1:
|
has_chunks = any(isinstance(msg, provider_message.MessageChunk) for msg in query.resp_messages)
|
||||||
# Multiple chains (split strategy): send each sequentially
|
# TODO 命令与流式的兼容性问题
|
||||||
for i, chain in enumerate(query.resp_message_chain):
|
if await query.adapter.is_stream_output_supported() and has_chunks:
|
||||||
is_first = i == 0
|
is_final = [msg.is_final for msg in query.resp_messages][0]
|
||||||
|
await query.adapter.reply_message_chunk(
|
||||||
if (
|
message_source=query.message_event,
|
||||||
is_first
|
bot_message=query.resp_messages[-1],
|
||||||
and query.pipeline_config['output']['misc']['at-sender']
|
message=query.resp_message_chain[-1],
|
||||||
and isinstance(query.message_event, platform_events.GroupMessage)
|
quote_origin=quote_origin,
|
||||||
):
|
is_final=is_final,
|
||||||
chain.insert(0, platform_message.At(target=query.message_event.sender.id))
|
)
|
||||||
|
else:
|
||||||
|
await query.adapter.reply_message(
|
||||||
|
message_source=query.message_event,
|
||||||
|
message=query.resp_message_chain[-1],
|
||||||
|
quote_origin=quote_origin,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Send extra chains produced by long text split strategy
|
||||||
|
extra_chains = query.get_variable('_longtext_split_extra_chains')
|
||||||
|
if extra_chains:
|
||||||
|
for chain in extra_chains:
|
||||||
await query.adapter.reply_message(
|
await query.adapter.reply_message(
|
||||||
message_source=query.message_event,
|
message_source=query.message_event,
|
||||||
message=chain,
|
message=chain,
|
||||||
quote_origin=quote_origin if is_first else False,
|
quote_origin=False,
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
if query.pipeline_config['output']['misc']['at-sender'] and isinstance(
|
|
||||||
query.message_event, platform_events.GroupMessage
|
|
||||||
):
|
|
||||||
query.resp_message_chain[-1].insert(0, platform_message.At(target=query.message_event.sender.id))
|
|
||||||
|
|
||||||
has_chunks = any(isinstance(msg, provider_message.MessageChunk) for msg in query.resp_messages)
|
|
||||||
# TODO 命令与流式的兼容性问题
|
|
||||||
if await query.adapter.is_stream_output_supported() and has_chunks:
|
|
||||||
is_final = [msg.is_final for msg in query.resp_messages][0]
|
|
||||||
await query.adapter.reply_message_chunk(
|
|
||||||
message_source=query.message_event,
|
|
||||||
bot_message=query.resp_messages[-1],
|
|
||||||
message=query.resp_message_chain[-1],
|
|
||||||
quote_origin=quote_origin,
|
|
||||||
is_final=is_final,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await query.adapter.reply_message(
|
|
||||||
message_source=query.message_event,
|
|
||||||
message=query.resp_message_chain[-1],
|
|
||||||
quote_origin=quote_origin,
|
|
||||||
)
|
)
|
||||||
|
query.set_variable('_longtext_split_extra_chains', None)
|
||||||
|
|
||||||
return entities.StageProcessResult(result_type=entities.ResultType.CONTINUE, new_query=query)
|
return entities.StageProcessResult(result_type=entities.ResultType.CONTINUE, new_query=query)
|
||||||
|
|||||||
Reference in New Issue
Block a user