Skip to content

Commit

Permalink
Merge pull request elizaOS#482 from bmgalego/improvements
Browse files Browse the repository at this point in the history
feat: Improvements
  • Loading branch information
ponderingdemocritus authored Nov 21, 2024
2 parents 693600b + be5e605 commit 83a5ae2
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 127 deletions.
9 changes: 9 additions & 0 deletions agent/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ function intializeDbCache(character: Character, db: IDatabaseCacheAdapter) {
async function startAgent(character: Character, directClient: DirectClient) {
try {
character.id ??= stringToUuid(character.name);
character.username ??= character.name;

const token = getTokenForProvider(character.modelProvider, character);
const dataDir = path.join(__dirname, "../data");
Expand All @@ -290,6 +291,8 @@ async function startAgent(character: Character, directClient: DirectClient) {
const cache = intializeDbCache(character, db);
const runtime = createAgent(character, db, cache, token);

await runtime.initialize();

const clients = await initializeClients(character, runtime);

directClient.registerAgent(runtime);
Expand Down Expand Up @@ -349,9 +352,15 @@ const rl = readline.createInterface({
output: process.stdout,
});

rl.on("SIGINT", () => {
rl.close();
process.exit(0);
});

async function handleUserInput(input, agentId) {
if (input.toLowerCase() === "exit") {
rl.close();
process.exit(0);
return;
}

Expand Down
215 changes: 141 additions & 74 deletions packages/client-twitter/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,53 +218,56 @@ export class ClientBase extends EventEmitter {
}

async fetchHomeTimeline(count: number): Promise<Tweet[]> {
const homeTimeline = await this.twitterClient.fetchHomeTimeline(
count,
[]
elizaLogger.debug("fetching home timeline");
const homeTimeline = await this.twitterClient.getUserTweets(
this.profile.id,
count
);

return homeTimeline
.filter((t) => t.__typename !== "TweetWithVisibilityResults")
.map((tweet) => {
// console.log("tweet is", tweet);
const obj = {
id: tweet.rest_id,
name:
tweet.name ??
tweet.core?.user_results?.result?.legacy.name,
username:
tweet.username ??
tweet.core?.user_results?.result?.legacy.screen_name,
text: tweet.text ?? tweet.legacy?.full_text,
inReplyToStatusId:
tweet.inReplyToStatusId ??
tweet.legacy?.in_reply_to_status_id_str,
createdAt: tweet.createdAt ?? tweet.legacy?.created_at,
userId: tweet.userId ?? tweet.legacy?.user_id_str,
conversationId:
tweet.conversationId ??
tweet.legacy?.conversation_id_str,
hashtags: tweet.hashtags ?? tweet.legacy?.entities.hashtags,
mentions:
tweet.mentions ?? tweet.legacy?.entities.user_mentions,
photos:
tweet.photos ??
tweet.legacy?.entities.media?.filter(
(media) => media.type === "photo"
) ??
[],
thread: [],
urls: tweet.urls ?? tweet.legacy?.entities.urls,
videos:
tweet.videos ??
tweet.legacy?.entities.media?.filter(
(media) => media.type === "video"
) ??
[],
};
// console.log("obj is", obj);
return obj;
});
// console.dir(homeTimeline, { depth: Infinity });

return homeTimeline.tweets;
// .filter((t) => t.__typename !== "TweetWithVisibilityResults")
// .map((tweet) => {
// // console.log("tweet is", tweet);
// const obj = {
// id: tweet.id,
// name:
// tweet.name ??
// tweet. ?.user_results?.result?.legacy.name,
// username:
// tweet.username ??
// tweet.core?.user_results?.result?.legacy.screen_name,
// text: tweet.text ?? tweet.legacy?.full_text,
// inReplyToStatusId:
// tweet.inReplyToStatusId ??
// tweet.legacy?.in_reply_to_status_id_str,
// createdAt: tweet.createdAt ?? tweet.legacy?.created_at,
// userId: tweet.userId ?? tweet.legacy?.user_id_str,
// conversationId:
// tweet.conversationId ??
// tweet.legacy?.conversation_id_str,
// hashtags: tweet.hashtags ?? tweet.legacy?.entities.hashtags,
// mentions:
// tweet.mentions ?? tweet.legacy?.entities.user_mentions,
// photos:
// tweet.photos ??
// tweet.legacy?.entities.media?.filter(
// (media) => media.type === "photo"
// ) ??
// [],
// thread: [],
// urls: tweet.urls ?? tweet.legacy?.entities.urls,
// videos:
// tweet.videos ??
// tweet.legacy?.entities.media?.filter(
// (media) => media.type === "video"
// ) ??
// [],
// };
// // console.log("obj is", obj);
// return obj;
// });
}

async fetchSearchTweets(
Expand Down Expand Up @@ -305,6 +308,8 @@ export class ClientBase extends EventEmitter {
}

private async populateTimeline() {
elizaLogger.debug("populating timeline...");

const cachedTimeline = await this.getCachedTimeline();

// Check if the cache file exists
Expand All @@ -322,6 +327,8 @@ export class ClientBase extends EventEmitter {
),
});

//TODO: load tweets not in cache?

// Create a Set to store the IDs of existing memories
const existingMemoryIds = new Set(
existingMemories.map((memory) => memory.id.toString())
Expand All @@ -343,23 +350,42 @@ export class ClientBase extends EventEmitter {
)
);

console.log({
processingTweets: tweetsToSave
.map((tweet) => tweet.id)
.join(","),
});

// Save the missing tweets as memories
for (const tweet of tweetsToSave) {
elizaLogger.log("Saving Tweet", tweet.id);

const roomId = stringToUuid(
tweet.conversationId + "-" + this.runtime.agentId
);
const tweetuserId =

const userId =
tweet.userId === this.profile.id
? this.runtime.agentId
: stringToUuid(tweet.userId);

await this.runtime.ensureConnection(
tweetuserId,
roomId,
tweet.username,
tweet.name,
"twitter"
);
if (tweet.userId === this.profile.id) {
await this.runtime.ensureConnection(
this.runtime.agentId,
roomId,
this.profile.username,
this.profile.screenName,
"twitter"
);
} else {
await this.runtime.ensureConnection(
userId,
roomId,
tweet.username,
tweet.name,
"twitter"
);
}

const content = {
text: tweet.text,
Expand All @@ -381,6 +407,7 @@ export class ClientBase extends EventEmitter {
await this.runtime.messageManager.getMemoryById(
stringToUuid(tweet.id + "-" + this.runtime.agentId)
);

if (memory) {
elizaLogger.log(
"Memory already exists, skipping timeline population"
Expand All @@ -390,13 +417,15 @@ export class ClientBase extends EventEmitter {

await this.runtime.messageManager.createMemory({
id: stringToUuid(tweet.id + "-" + this.runtime.agentId),
userId: tweetuserId,
userId,
content: content,
agentId: this.runtime.agentId,
roomId,
embedding: embeddingZeroVector,
createdAt: tweet.timestamp * 1000,
});

await this.cacheTweet(tweet);
}

elizaLogger.log(
Expand All @@ -406,6 +435,8 @@ export class ClientBase extends EventEmitter {
}
}

const timeline = await this.fetchHomeTimeline(cachedTimeline ? 10 : 50);

// Get the most recent 20 mentions and interactions
const mentionsAndInteractions = await this.fetchSearchTweets(
`@${this.runtime.getSetting("TWITTER_USERNAME")}`,
Expand All @@ -414,7 +445,7 @@ export class ClientBase extends EventEmitter {
);

// Combine the timeline tweets and mentions/interactions
const allTweets = [...mentionsAndInteractions.tweets];
const allTweets = [...timeline, ...mentionsAndInteractions.tweets];

// Create a Set to store unique tweet IDs
const tweetIdsToCheck = new Set<string>();
Expand Down Expand Up @@ -448,30 +479,46 @@ export class ClientBase extends EventEmitter {
)
);

elizaLogger.debug({
processingTweets: tweetsToSave.map((tweet) => tweet.id).join(","),
});

await this.runtime.ensureUserExists(
this.runtime.agentId,
this.runtime.getSetting("TWITTER_USERNAME"),
this.profile.username,
this.runtime.character.name,
"twitter"
);

// Save the new tweets as memories
for (const tweet of tweetsToSave) {
elizaLogger.log("Saving Tweet", tweet.id);

const roomId = stringToUuid(
tweet.conversationId + "-" + this.runtime.agentId
);
const tweetuserId =
const userId =
tweet.userId === this.profile.id
? this.runtime.agentId
: stringToUuid(tweet.userId);

await this.runtime.ensureConnection(
tweetuserId,
roomId,
tweet.username,
tweet.name,
"twitter"
);
if (tweet.userId === this.profile.id) {
await this.runtime.ensureConnection(
this.runtime.agentId,
roomId,
this.profile.username,
this.profile.screenName,
"twitter"
);
} else {
await this.runtime.ensureConnection(
userId,
roomId,
tweet.username,
tweet.name,
"twitter"
);
}

const content = {
text: tweet.text,
Expand All @@ -484,17 +531,20 @@ export class ClientBase extends EventEmitter {

await this.runtime.messageManager.createMemory({
id: stringToUuid(tweet.id + "-" + this.runtime.agentId),
userId: tweetuserId,
userId,
content: content,
agentId: this.runtime.agentId,
roomId,
embedding: embeddingZeroVector,
createdAt: tweet.timestamp * 1000,
});

await this.cacheTweet(tweet);
}

// Cache
await this.cacheTimeline(allTweets);
await this.cacheTimeline(timeline);
await this.cacheMentions(mentionsAndInteractions.tweets);
}

async setCookiesFromArray(cookiesArray: any[]) {
Expand Down Expand Up @@ -524,7 +574,7 @@ export class ClientBase extends EventEmitter {
recentMessage.length > 0 &&
recentMessage[0].content === message.content
) {
console.log("Message already saved", recentMessage[0].id);
elizaLogger.debug("Message already saved", recentMessage[0].id);
} else {
await this.runtime.messageManager.createMemory({
...message,
Expand Down Expand Up @@ -568,7 +618,16 @@ export class ClientBase extends EventEmitter {
async cacheTimeline(timeline: Tweet[]) {
await this.runtime.cacheManager.set(
`twitter/${this.profile.username}/timeline`,
timeline
timeline,
{ expires: 10 * 1000 }
);
}

async cacheMentions(mentions: Tweet[]) {
await this.runtime.cacheManager.set(
`twitter/${this.profile.username}/mentions`,
mentions,
{ expires: 10 * 1000 }
);
}

Expand All @@ -585,10 +644,21 @@ export class ClientBase extends EventEmitter {
);
}

async fetchProfile(username: string): Promise<TwitterProfile> {
const cached = await this.runtime.cacheManager.get<TwitterProfile>(
async getCachedProfile(username: string) {
return await this.runtime.cacheManager.get<TwitterProfile>(
`twitter/${username}/profile`
);
}

async cacheProfile(profile: TwitterProfile) {
await this.runtime.cacheManager.set(
`twitter/${profile.username}/profile`,
profile
);
}

async fetchProfile(username: string): Promise<TwitterProfile> {
const cached = await this.getCachedProfile(username);

if (cached) return cached;

Expand All @@ -612,10 +682,7 @@ export class ClientBase extends EventEmitter {
} satisfies TwitterProfile;
});

this.runtime.cacheManager.set(
`twitter/${username}/profile`,
profile
);
this.cacheProfile(profile);

return profile;
} catch (error) {
Expand Down
2 changes: 2 additions & 0 deletions packages/client-twitter/src/interactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ export class TwitterInteractionClient {
twitterMessageHandlerTemplate,
});

elizaLogger.debug("Interactions prompt:\n" + context);

const response = await generateMessageResponse({
runtime: this.runtime,
context,
Expand Down
Loading

0 comments on commit 83a5ae2

Please sign in to comment.