Skip to content

Commit 3f2808f

Browse files
committed
chore: improve model
1 parent 46c2312 commit 3f2808f

File tree

12 files changed

+101
-98
lines changed

12 files changed

+101
-98
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

agents/anda_bot/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "anda_bot"
33
description = "I'm Anda ICP, Digital panda 🐼 by Anda framework. Secured in TEE, memories on ICP chain.✨"
44
repository = "https://github.com/ldclabs/anda/tree/main/agents/anda_bot"
55
publish = false
6-
version = "0.4.2"
6+
version = "0.4.3"
77
edition.workspace = true
88
keywords.workspace = true
99
categories.workspace = true

agents/anda_bot/deployment_cn.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ cargo run -p anda_bot -- start-local
2323

2424
3. 在 linux 环境下可直接下载 anda_bot 可执行文件。
2525
```sh
26-
wget https://github.com/ldclabs/anda/releases/download/v0.4.1/anda_bot
26+
wget https://github.com/ldclabs/anda/releases/download/v0.4.3/anda_bot
2727
chmod +x anda_bot
2828
```
2929

agents/anda_bot/deployment_en.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ cargo run -p anda_bot -- start-local
2424

2525
3. Download the executable directly on Linux:
2626
```sh
27-
wget https://github.com/ldclabs/anda/releases/download/v0.4.1/anda_bot
27+
wget https://github.com/ldclabs/anda/releases/download/v0.4.3/anda_bot
2828
chmod +x anda_bot
2929
```
3030

agents/anda_bot/nitro_enclave/amd64.Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ RUN chmod +x ic_tee_daemon
2525
RUN wget -O ic_tee_nitro_gateway https://github.com/ldclabs/ic-tee/releases/download/v0.3.0/ic_tee_nitro_gateway
2626
RUN chmod +x ic_tee_nitro_gateway
2727

28-
RUN wget -O anda_bot https://github.com/ldclabs/anda/releases/download/v0.4.2/anda_bot
28+
RUN wget -O anda_bot https://github.com/ldclabs/anda/releases/download/v0.4.3/anda_bot
2929
RUN chmod +x anda_bot
3030

3131
FROM debian:bookworm-slim AS runtime

agents/anda_bot/src/twitter.rs

Lines changed: 55 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
use agent_twitter_client::{models::Tweet, scraper::Scraper, search::SearchMode};
22
use anda_core::{Agent, BoxError, CompletionFeatures, StateFeatures};
33
use anda_engine::{
4-
context::{AgentCtx, CacheStoreFeatures, ANONYMOUS},
5-
engine::Engine,
4+
context::{ANONYMOUS, AgentCtx, CacheStoreFeatures},
5+
engine::{Engine, NAME},
66
extension::character::CharacterAgent,
77
rand_number,
88
};
99
use anda_lancedb::knowledge::KnowledgeStore;
1010
use std::sync::Arc;
1111
use tokio::{
1212
sync::RwLock,
13-
time::{sleep, Duration},
13+
time::{Duration, sleep},
1414
};
1515
use tokio_util::sync::CancellationToken;
1616

@@ -146,7 +146,7 @@ impl TwitterDaemon {
146146
let ctx = self.engine.ctx_with(
147147
&self.agent.as_ref().name(),
148148
ANONYMOUS,
149-
Some(self.agent.character.username.clone()),
149+
Some(NAME.to_string()),
150150
)?;
151151
let req = self
152152
.agent
@@ -157,7 +157,7 @@ impl TwitterDaemon {
157157
Be direct and concise. No questions, hashtags, or emojis.\
158158
"
159159
.to_string(),
160-
ctx.user(),
160+
Some(NAME.to_string()),
161161
)
162162
.append_documents(knowledges.into());
163163
let res = ctx.completion(req).await?;
@@ -301,9 +301,11 @@ impl TwitterDaemon {
301301
let res = self.agent.run(ctx.clone(), tweet_text, None).await?;
302302
if res.failed_reason.is_none() {
303303
// Reply to the original tweet
304-
let tweet: Option<&str> = tweet.id.as_deref();
305304
let content = remove_quotes(res.content);
306-
let _ = self.scraper.send_tweet(&content, tweet, None).await?;
305+
let _ = self
306+
.scraper
307+
.send_tweet(&content, Some(&tweet_id), None)
308+
.await?;
307309

308310
log::info!(
309311
tweet_user = tweet_user,
@@ -368,40 +370,37 @@ impl TwitterDaemon {
368370
tweet_content: &str,
369371
tweet_id: &str,
370372
) -> Result<bool, BoxError> {
371-
if self
373+
let req = self
372374
.agent
373-
.attention
374-
.should_retweet(ctx, tweet_content)
375-
.await
376-
{
377-
let req = self
378-
.agent
379-
.character
380-
.to_request(
381-
"\
382-
Reply the tweet with a single clear, natural sentence. No hashtags.\
383-
"
384-
.to_string(),
385-
ctx.user(),
386-
)
387-
.context(
388-
tweet_id.to_string(),
389-
format!("Tweet content:\n{tweet_content}"),
390-
);
391-
let res = ctx.completion(req).await?;
392-
match res.failed_reason {
393-
Some(reason) => {
394-
return Err(format!("Failed to generate response for tweet: {reason}").into());
395-
}
396-
None => {
375+
.character
376+
.to_request(
377+
format!("\
378+
Respond the tweet AS **{}** would - only reply if your persona deems it necessary. When engaging:\n\
379+
1. Use your character's unique voice and communication style naturally\n\
380+
2. Keep responses to one authentic-sentence without hashtags\n\
381+
3. Return empty if your persona wouldn't respond to this tweet\n\n\
382+
## Tweet Content:\n{:?}\
383+
", self.agent.character.name, tweet_content),
384+
Some(NAME.to_string()),
385+
);
386+
387+
let res = ctx.completion(req).await?;
388+
match res.failed_reason {
389+
Some(reason) => {
390+
return Err(format!("Failed to generate response for tweet: {reason}").into());
391+
}
392+
None => {
393+
let content = remove_quotes(res.content);
394+
if !content.is_empty() {
397395
let _ = self
398396
.scraper
399-
.send_tweet(&remove_quotes(res.content), Some(tweet_id), None)
397+
.send_tweet(&content, Some(tweet_id), None)
400398
.await?;
401399
return Ok(true);
402400
}
403401
}
404402
}
403+
405404
Ok(false)
406405
}
407406

@@ -411,30 +410,31 @@ impl TwitterDaemon {
411410
tweet_content: &str,
412411
tweet_id: &str,
413412
) -> Result<bool, BoxError> {
414-
if self.agent.attention.should_quote(ctx, tweet_content).await {
415-
let req = self
416-
.agent
417-
.character
418-
.to_request(
419-
"\
420-
Quote the tweet with a single clear, natural sentence. No hashtags.\
421-
"
422-
.to_string(),
423-
ctx.user(),
424-
)
425-
.context(
426-
tweet_id.to_string(),
427-
format!("Tweet content:\n{tweet_content}"),
428-
);
429-
let res = ctx.completion(req).await?;
430-
match res.failed_reason {
431-
Some(reason) => {
432-
return Err(format!("Failed to generate response for tweet: {reason}").into());
433-
}
434-
None => {
413+
let req = self
414+
.agent
415+
.character
416+
.to_request(
417+
format!("\
418+
Respond the tweet AS **{}** would - only reply if your persona deems it necessary. When engaging:\n\
419+
1. Use your character's unique voice and communication style naturally\n\
420+
2. Keep responses to one authentic-sentence without hashtags\n\
421+
3. Return empty if your persona wouldn't respond to this tweet\n\n\
422+
## Tweet Content:\n{:?}\
423+
", self.agent.character.name, tweet_content),
424+
Some(NAME.to_string()),
425+
);
426+
427+
let res = ctx.completion(req).await?;
428+
match res.failed_reason {
429+
Some(reason) => {
430+
return Err(format!("Failed to generate response for tweet: {reason}").into());
431+
}
432+
None => {
433+
let content = remove_quotes(res.content);
434+
if !content.is_empty() {
435435
let _ = self
436436
.scraper
437-
.send_quote_tweet(&remove_quotes(res.content), tweet_id, None)
437+
.send_tweet(&content, Some(tweet_id), None)
438438
.await?;
439439
return Ok(true);
440440
}

anda_core/src/model.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ pub struct CompletionRequest {
234234
}
235235

236236
impl CompletionRequest {
237+
/// Adds a document to the request
237238
pub fn context(mut self, id: String, text: String) -> Self {
238239
self.documents.0.push(Document {
239240
id,
@@ -243,15 +244,32 @@ impl CompletionRequest {
243244
self
244245
}
245246

247+
/// Adds multiple documents to the request
246248
pub fn append_documents(mut self, docs: Documents) -> Self {
247249
self.documents.0.extend(docs.0);
248250
self
249251
}
250252

253+
/// Adds multiple tools to the request
251254
pub fn append_tools(mut self, tools: Vec<FunctionDefinition>) -> Self {
252255
self.tools.extend(tools);
253256
self
254257
}
258+
259+
/// Returns the prompt with context if available
260+
pub fn prompt_with_context(&self) -> Option<String> {
261+
if self.documents.0.is_empty() && self.prompt.is_empty() {
262+
return None;
263+
}
264+
265+
if self.documents.0.is_empty() {
266+
Some(self.prompt.clone())
267+
} else if self.prompt.is_empty() {
268+
Some(format!("{}", self.documents))
269+
} else {
270+
Some(format!("{}\n\n{}", self.documents, self.prompt))
271+
}
272+
}
255273
}
256274

257275
/// Represents a text embedding with its original text and vector representation
@@ -298,6 +316,7 @@ pub fn evaluate_tokens(content: &str) -> usize {
298316
#[cfg(test)]
299317
mod tests {
300318
use super::*;
319+
use serde_json::{json, to_string};
301320

302321
#[test]
303322
fn test_prompt() {
@@ -321,11 +340,22 @@ mod tests {
321340
.into(),
322341
..Default::default()
323342
};
324-
let prompt = format!("{}\n\n{}", req.documents, req.prompt);
343+
let prompt = req.prompt_with_context().unwrap();
325344
println!("{}", prompt);
326345
assert_eq!(
327346
prompt,
328347
"<attachments>\n<doc id=\"1\">\n\"Test document 1.\"\n</doc>\n<doc id=\"2\">\n<meta a=\"b\" key=\"value\" />\n\"Test document 2.\"\n</doc>\n</attachments>\n\nThis is a test prompt."
329348
);
349+
350+
let msg = json!(Message {
351+
role: "user".into(),
352+
content: prompt.into(),
353+
name: req.prompter_name,
354+
..Default::default()
355+
});
356+
assert_eq!(
357+
to_string(&msg).unwrap(),
358+
r#"{"content":"<attachments>\n<doc id=\"1\">\n\"Test document 1.\"\n</doc>\n<doc id=\"2\">\n<meta a=\"b\" key=\"value\" />\n\"Test document 2.\"\n</doc>\n</attachments>\n\nThis is a test prompt.","role":"user"}"#
359+
);
330360
}
331361
}

anda_engine/src/engine.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ use crate::{
4747
};
4848

4949
pub static ROOT_PATH: &str = "_";
50+
pub static NAME: &str = "Anda Engine";
5051

5152
/// Engine is the core component that manages agents, tools, and execution context.
5253
/// It provides methods to interact with agents, call tools, and manage execution.

anda_engine/src/extension/character.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use super::{
4242
segmenter::DocumentSegmenter,
4343
};
4444

45-
use crate::{context::AgentCtx, store::MAX_STORE_OBJECT_SIZE};
45+
use crate::{context::AgentCtx, engine::NAME, store::MAX_STORE_OBJECT_SIZE};
4646

4747
const MAX_CHAT_HISTORY: usize = 42;
4848
const CHAT_HISTORY_TTI: Duration = Duration::from_secs(3600 * 24 * 7);
@@ -275,10 +275,9 @@ impl Character {
275275

276276
CompletionRequest {
277277
system: Some(system),
278-
system_name: Some(self.name.clone()),
279278
prompt,
280279
prompter_name,
281-
temperature: Some(1.3),
280+
temperature: Some(1.5),
282281
..Default::default()
283282
}
284283
}
@@ -385,7 +384,7 @@ impl<K: KnowledgeFeatures + VectorSearchFeatures> CharacterAgent<K> {
385384
",
386385
content,
387386
),
388-
None,
387+
Some(NAME.to_string()),
389388
);
390389

391390
match ctx.completion(req).await {

anda_engine/src/model/deepseek.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -252,22 +252,13 @@ impl CompletionFeaturesDyn for CompletionModel {
252252
vec![]
253253
};
254254

255-
// Add context documents to chat history
256-
if !req.documents.is_empty() {
257-
full_history.push(json!(Message {
258-
role: "user".into(),
259-
content: format!("{}", req.documents).into(),
260-
..Default::default()
261-
}));
262-
}
263-
264255
// Extend existing chat history
265256
full_history.append(&mut req.chat_history);
266257

267-
if !req.prompt.is_empty() {
258+
if let Some(prompt) = req.prompt_with_context() {
268259
full_history.push(json!(Message {
269260
role: "user".into(),
270-
content: req.prompt.into(),
261+
content: prompt.into(),
271262
name: req.prompter_name,
272263
..Default::default()
273264
}));

0 commit comments

Comments
 (0)