fix: stabilize rpg creation entry and opening cg
This commit is contained in:
@@ -93,15 +93,74 @@ where
|
||||
F: FnMut(&str),
|
||||
{
|
||||
let mut latest_reply_text = String::new();
|
||||
let turn_output = match request_stream_creation_agent_json_turn_once(
|
||||
llm_client,
|
||||
system_prompt.clone(),
|
||||
user_prompt.clone(),
|
||||
enable_web_search,
|
||||
on_reply_update,
|
||||
&mut latest_reply_text,
|
||||
!enable_web_search,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(turn_output) => turn_output,
|
||||
Err(CreationAgentJsonTurnFailure::Stream(error))
|
||||
if enable_web_search && is_web_search_tool_unavailable(&error) =>
|
||||
{
|
||||
tracing::warn!(
|
||||
error = %error,
|
||||
"创作 Agent 流式联网搜索插件不可用,自动降级为无联网搜索重试"
|
||||
);
|
||||
latest_reply_text.clear();
|
||||
request_stream_creation_agent_json_turn_once(
|
||||
llm_client,
|
||||
system_prompt,
|
||||
user_prompt,
|
||||
false,
|
||||
on_reply_update,
|
||||
&mut latest_reply_text,
|
||||
true,
|
||||
)
|
||||
.await?
|
||||
}
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
|
||||
let reply_text = read_reply_text(&turn_output.parsed);
|
||||
if let Some(reply_text) = reply_text.as_deref()
|
||||
&& reply_text != latest_reply_text
|
||||
{
|
||||
on_reply_update(reply_text);
|
||||
}
|
||||
|
||||
Ok(turn_output)
|
||||
}
|
||||
|
||||
async fn request_stream_creation_agent_json_turn_once<F>(
|
||||
llm_client: &LlmClient,
|
||||
system_prompt: String,
|
||||
user_prompt: String,
|
||||
enable_web_search: bool,
|
||||
on_reply_update: &mut F,
|
||||
latest_reply_text: &mut String,
|
||||
emit_reply_updates: bool,
|
||||
) -> Result<CreationAgentJsonTurnOutput, CreationAgentJsonTurnFailure>
|
||||
where
|
||||
F: FnMut(&str),
|
||||
{
|
||||
let response = llm_client
|
||||
.stream_text(
|
||||
build_creation_agent_llm_request(system_prompt, user_prompt, enable_web_search),
|
||||
|delta: &LlmStreamDelta| {
|
||||
if !emit_reply_updates {
|
||||
return;
|
||||
}
|
||||
if let Some(reply_progress) =
|
||||
extract_reply_text_from_partial_json(delta.accumulated_text.as_str())
|
||||
&& reply_progress != latest_reply_text
|
||||
&& reply_progress != *latest_reply_text
|
||||
{
|
||||
latest_reply_text = reply_progress.clone();
|
||||
*latest_reply_text = reply_progress.clone();
|
||||
on_reply_update(reply_progress.as_str());
|
||||
}
|
||||
},
|
||||
@@ -110,12 +169,6 @@ where
|
||||
.map_err(CreationAgentJsonTurnFailure::Stream)?;
|
||||
let parsed = parse_json_response_text(response.content.as_str())
|
||||
.map_err(|_| CreationAgentJsonTurnFailure::Parse)?;
|
||||
let reply_text = read_reply_text(&parsed);
|
||||
if let Some(reply_text) = reply_text.as_deref()
|
||||
&& reply_text != latest_reply_text
|
||||
{
|
||||
on_reply_update(reply_text);
|
||||
}
|
||||
|
||||
Ok(CreationAgentJsonTurnOutput { parsed })
|
||||
}
|
||||
@@ -327,6 +380,7 @@ mod tests {
|
||||
let server = spawn_capturing_mock_server(vec![
|
||||
MockResponse {
|
||||
body: concat!(
|
||||
"data: {\"type\":\"response.output_text.delta\",\"delta\":\"我需要先搜索玩具王国资料。\"}\n\n",
|
||||
"data: {\"type\":\"error\",\"code\":\"ToolNotOpen\",\"message\":\"Your account has not activated web search.\"}\n\n",
|
||||
"data: [DONE]\n\n"
|
||||
)
|
||||
@@ -391,6 +445,55 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn stream_turn_keeps_partial_updates_when_web_search_is_disabled() {
|
||||
let server = spawn_capturing_mock_server(vec![MockResponse {
|
||||
body: concat!(
|
||||
"data: {\"type\":\"response.output_text.delta\",\"delta\":\"{\\\"replyText\\\":\\\"我先\"}\n\n",
|
||||
"data: {\"type\":\"response.output_text.delta\",\"delta\":\"把玩具王国定住。\\\",\\\"progressPercent\\\":12}\"}\n\n",
|
||||
"data: {\"type\":\"response.completed\"}\n\n",
|
||||
)
|
||||
.to_string(),
|
||||
}]);
|
||||
let config = LlmConfig::new(
|
||||
LlmProvider::Ark,
|
||||
server.base_url,
|
||||
"test-key".to_string(),
|
||||
"test-model".to_string(),
|
||||
30_000,
|
||||
0,
|
||||
1,
|
||||
)
|
||||
.expect("LLM config should build");
|
||||
let llm_client = platform_llm::LlmClient::new(config).expect("LLM client should build");
|
||||
let mut visible_replies = Vec::new();
|
||||
|
||||
let output = stream_creation_agent_json_turn(
|
||||
Some(&llm_client),
|
||||
"系统提示".to_string(),
|
||||
"用户提示",
|
||||
false,
|
||||
CreationAgentLlmTurnErrorMessages {
|
||||
model_unavailable: "模型不可用",
|
||||
generation_failed: "生成失败",
|
||||
parse_failed: "解析失败",
|
||||
},
|
||||
|text| visible_replies.push(text.to_string()),
|
||||
|message| message,
|
||||
)
|
||||
.await
|
||||
.expect("stream without web search should succeed");
|
||||
|
||||
assert_eq!(
|
||||
output.parsed["replyText"].as_str(),
|
||||
Some("我先把玩具王国定住。")
|
||||
);
|
||||
assert_eq!(
|
||||
visible_replies,
|
||||
vec!["我先".to_string(), "我先把玩具王国定住。".to_string()]
|
||||
);
|
||||
}
|
||||
|
||||
struct MockResponse {
|
||||
body: String,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user