Skip to content

Commit f4be6a6

Browse files
committed
chore: improve gen_schema_for
1 parent 94aabf1 commit f4be6a6

File tree

14 files changed

+105
-22
lines changed

14 files changed

+105
-22
lines changed

agents/anda_assistant/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "anda_assistant"
33
description = "Anda -- an AI Assistant powered by the Knowledge Interaction Protocol (KIP)."
44
repository = "https://github.com/ldclabs/anda/tree/main/agents/anda_assistant"
55
publish = true
6-
version = "0.4.6"
6+
version = "0.4.7"
77
edition.workspace = true
88
keywords.workspace = true
99
categories.workspace = true

anda_core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "anda_core"
33
description = "Core types and traits for Anda -- an AI agent framework built with Rust, powered by ICP and TEEs."
44
repository = "https://github.com/ldclabs/anda/tree/main/anda_core"
55
publish = true
6-
version.workspace = true
6+
version = "0.9.9"
77
edition.workspace = true
88
keywords.workspace = true
99
categories.workspace = true

anda_core/src/json.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub fn gen_schema_for<T: JsonSchema>() -> serde_json::Value {
1919
let mut schema = root_schema_for::<T>();
2020
schema.remove("title");
2121
schema.remove("description");
22+
if schema.get("required").is_none() {
23+
schema.insert("required".to_string(), serde_json::json!([]));
24+
}
2225
schema.to_value()
2326
}
2427

anda_core/src/model.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ pub struct AgentOutput {
9494
/// The conversation ID.
9595
#[serde(skip_serializing_if = "Option::is_none")]
9696
pub conversation: Option<u64>,
97+
98+
/// The model used by the agent.
99+
#[serde(skip_serializing_if = "Option::is_none")]
100+
pub model: Option<String>,
97101
}
98102

99103
/// Represents a message send to LLM for completion.

anda_core/src/model/completion.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ pub trait CompletionFeatures: Sized {
1313
req: CompletionRequest,
1414
resources: Vec<Resource>,
1515
) -> impl Future<Output = Result<AgentOutput, BoxError>> + Send;
16+
17+
/// Returns the name of the model.
18+
fn model_name(&self) -> String;
1619
}
1720

1821
/// Represents a general completion request that can be sent to a completion model provider.

anda_engine/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "anda_engine"
33
description = "Agents engine for Anda -- an AI agent framework built with Rust, powered by ICP and TEEs."
44
repository = "https://github.com/ldclabs/anda/tree/main/anda_engine"
55
publish = true
6-
version = "0.9.11"
6+
version = "0.9.12"
77
edition.workspace = true
88
keywords.workspace = true
99
categories.workspace = true

anda_engine/src/context/agent.rs

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,10 @@ impl AgentContext for AgentCtx {
515515
}
516516

517517
impl CompletionFeatures for AgentCtx {
518+
fn model_name(&self) -> String {
519+
self.model.model_name()
520+
}
521+
518522
/// Executes a completion request with automatic tool call handling.
519523
///
520524
/// This method handles the completion request in a loop, automatically executing
@@ -991,33 +995,37 @@ impl CompletionRunner {
991995
self.step += 1;
992996

993997
let mut output = self.model.completion(self.req.clone()).await?;
998+
output.model = Some(self.model.model_name());
999+
9941000
self.usage.accumulate(&output.usage);
9951001

9961002
// If the primary model returns a failed result (failed_reason exists),
9971003
// and a fallback model is configured, switch to the fallback model and retry.
9981004
// After switching, subsequent steps will keep using the fallback model.
9991005
if output.failed_reason.is_some()
1000-
&& let Some(fallback) = self.fallback_model.take() {
1001-
let primary_reason = output
1002-
.failed_reason
1003-
.clone()
1004-
.unwrap_or_else(|| "unknown error".to_string());
1005-
1006-
self.model = fallback;
1007-
let mut output2 = self.model.completion(self.req.clone()).await?;
1008-
self.usage.accumulate(&output2.usage);
1009-
1010-
if let Some(fallback_reason) = output2.failed_reason.clone() {
1011-
output2.failed_reason = Some(format!(
1012-
"primary model failed: {}; fallback model failed: {}",
1013-
primary_reason, fallback_reason
1014-
));
1015-
return Ok(Some(self.final_output(output2)));
1016-
}
1017-
1018-
output = output2;
1006+
&& let Some(fallback) = self.fallback_model.take()
1007+
{
1008+
let primary_reason = output
1009+
.failed_reason
1010+
.clone()
1011+
.unwrap_or_else(|| "unknown error".to_string());
1012+
1013+
self.model = fallback;
1014+
let mut output2 = self.model.completion(self.req.clone()).await?;
1015+
output2.model = Some(self.model.model_name());
1016+
self.usage.accumulate(&output2.usage);
1017+
1018+
if let Some(fallback_reason) = output2.failed_reason.clone() {
1019+
output2.failed_reason = Some(format!(
1020+
"primary model failed: {}; fallback model failed: {}",
1021+
primary_reason, fallback_reason
1022+
));
1023+
return Ok(Some(self.final_output(output2)));
10191024
}
10201025

1026+
output = output2;
1027+
}
1028+
10211029
// 累计所有原始对话历史(包含初始的 req.raw_history 和 req.chat_history)
10221030
self.req.raw_history.append(&mut output.raw_history);
10231031
// 累计所有对话历史(不包含初始的 req.chat_history)
@@ -1220,6 +1228,10 @@ mod tests {
12201228
struct AlwaysFailCompleter;
12211229

12221230
impl CompletionFeaturesDyn for AlwaysFailCompleter {
1231+
fn model_name(&self) -> String {
1232+
"always_fail".to_string()
1233+
}
1234+
12231235
fn completion(
12241236
&self,
12251237
_req: CompletionRequest,
@@ -1235,6 +1247,10 @@ mod tests {
12351247
struct AlwaysOkCompleter;
12361248

12371249
impl CompletionFeaturesDyn for AlwaysOkCompleter {
1250+
fn model_name(&self) -> String {
1251+
"always_ok".to_string()
1252+
}
1253+
12381254
fn completion(
12391255
&self,
12401256
_req: CompletionRequest,

anda_engine/src/memory.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,4 +1125,11 @@ mod tests {
11251125
let args1: MemoryToolArgs = serde_json::from_str(&rt).unwrap();
11261126
assert_eq!(args, args1);
11271127
}
1128+
1129+
#[test]
1130+
fn test_list_prev_conversations_schema() {
1131+
let schema = gen_schema_for::<ListConversationsArgs>();
1132+
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
1133+
assert!(schema.get("required").is_some());
1134+
}
11281135
}

anda_engine/src/model.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ use crate::APP_USER_AGENT;
3636
pub trait CompletionFeaturesDyn: Send + Sync + 'static {
3737
/// Performs a completion request and returns a future with the agent's output
3838
fn completion(&self, req: CompletionRequest) -> BoxPinFut<Result<AgentOutput, BoxError>>;
39+
40+
fn model_name(&self) -> String;
3941
}
4042

4143
/// Trait for dynamic embedding features that can be used across threads
@@ -55,6 +57,10 @@ pub trait EmbeddingFeaturesDyn: Send + Sync + 'static {
5557
pub struct NotImplemented;
5658

5759
impl CompletionFeaturesDyn for NotImplemented {
60+
fn model_name(&self) -> String {
61+
"not_implemented".to_string()
62+
}
63+
5864
fn completion(&self, _req: CompletionRequest) -> BoxPinFut<Result<AgentOutput, BoxError>> {
5965
Box::pin(futures::future::ready(Err("not implemented".into())))
6066
}
@@ -79,6 +85,10 @@ impl EmbeddingFeaturesDyn for NotImplemented {
7985
pub struct MockImplemented;
8086

8187
impl CompletionFeaturesDyn for MockImplemented {
88+
fn model_name(&self) -> String {
89+
"not_implemented".to_string()
90+
}
91+
8292
fn completion(&self, req: CompletionRequest) -> BoxPinFut<Result<AgentOutput, BoxError>> {
8393
Box::pin(futures::future::ready(Ok(AgentOutput {
8494
content: req.prompt.clone(),
@@ -177,6 +187,10 @@ impl Model {
177187
}
178188
}
179189

190+
pub fn model_name(&self) -> String {
191+
self.completer.model_name()
192+
}
193+
180194
pub async fn completion(&self, req: CompletionRequest) -> Result<AgentOutput, BoxError> {
181195
self.completer.completion(req).await
182196
}

anda_engine/src/model/deepseek.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,10 @@ impl CompletionModel {
298298
}
299299

300300
impl CompletionFeatures for CompletionModel {
301+
fn model_name(&self) -> String {
302+
self.model.clone()
303+
}
304+
301305
async fn completion(
302306
&self,
303307
req: CompletionRequest,
@@ -308,6 +312,10 @@ impl CompletionFeatures for CompletionModel {
308312
}
309313

310314
impl CompletionFeaturesDyn for CompletionModel {
315+
fn model_name(&self) -> String {
316+
self.model.clone()
317+
}
318+
311319
fn completion(&self, mut req: CompletionRequest) -> BoxPinFut<Result<AgentOutput, BoxError>> {
312320
let model = self.model.clone();
313321
let client = self.client.clone();

0 commit comments

Comments
 (0)