Skip to content

Commit

Permalink
Merge branch 'develop' into feat/view-chat-history-with-agent-in-clie…
Browse files Browse the repository at this point in the history
…nt-UI
  • Loading branch information
wtfsayo authored Jan 15, 2025
2 parents f0eebe1 + 640b4e8 commit bb82372
Show file tree
Hide file tree
Showing 12 changed files with 501 additions and 274 deletions.
1 change: 1 addition & 0 deletions agent/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ import path from "path";
import { fileURLToPath } from "url";
import yargs from "yargs";


const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file
const __dirname = path.dirname(__filename); // get the name of the directory

Expand Down
1 change: 0 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"@rollup/plugin-terser": "0.1.0",
"@rollup/plugin-typescript": "11.1.6",
"@solana/web3.js": "1.95.8",
"@tavily/core": "^0.0.2",
"@types/fluent-ffmpeg": "2.1.27",
"@types/jest": "29.5.14",
"@types/mocha": "10.0.10",
Expand Down
25 changes: 1 addition & 24 deletions packages/core/src/generation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import {
ModelClass,
ModelProviderName,
ServiceType,
SearchResponse,
ActionResponse,
IVerifiableInferenceAdapter,
VerifiableInferenceOptions,
Expand All @@ -51,7 +50,7 @@ import {
TokenizerType,
} from "./types.ts";
import { fal } from "@fal-ai/client";
import { tavily } from "@tavily/core";

import BigNumber from "bignumber.js";
import {createPublicClient, http} from "viem";

Expand Down Expand Up @@ -1818,28 +1817,6 @@ export const generateCaption = async (
};
};

export const generateWebSearch = async (
query: string,
runtime: IAgentRuntime
): Promise<SearchResponse> => {
try {
const apiKey = runtime.getSetting("TAVILY_API_KEY") as string;
if (!apiKey) {
throw new Error("TAVILY_API_KEY is not set");
}
const tvly = tavily({ apiKey });
const response = await tvly.search(query, {
includeAnswer: true,
maxResults: 3, // 5 (default)
topic: "general", // "general"(default) "news"
searchDepth: "basic", // "basic"(default) "advanced"
includeImages: false, // false (default) true
});
return response;
} catch (error) {
elizaLogger.error("Error:", error);
}
};
/**
* Configuration options for generating objects with a model.
*/
Expand Down
23 changes: 1 addition & 22 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1418,28 +1418,6 @@ export interface ITeeLogService extends Service {
): Promise<boolean>;
}

export type SearchImage = {
url: string;
description?: string;
};

export type SearchResult = {
title: string;
url: string;
content: string;
rawContent?: string;
score: number;
publishedDate?: string;
};

export type SearchResponse = {
answer?: string;
query: string;
responseTime: number;
images: SearchImage[];
results: SearchResult[];
};

export enum ServiceType {
IMAGE_DESCRIPTION = "image_description",
TRANSCRIPTION = "transcription",
Expand All @@ -1456,6 +1434,7 @@ export enum ServiceType {
IRYS = "irys",
TEE_LOG = "tee_log",
GOPLUS_SECURITY = "goplus_security",
WEB_SEARCH = "web_search",
}

export enum LoggingLevel {
Expand Down
1 change: 0 additions & 1 deletion packages/core/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export default defineConfig({
"http",
"https",
// Add other modules you want to externalize
"@tavily/core",
"onnxruntime-node",
"sharp",
],
Expand Down
24 changes: 23 additions & 1 deletion packages/plugin-web-search/README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ TAVILY_API_KEY=your_api_key # Required: API key for search service

## Usage

Import and register the plugin in your Eliza configuration:
Import and register the plugin in your Eliza configuration.

```typescript
import { webSearchPlugin } from "@elizaos/plugin-web-search";
Expand All @@ -39,6 +39,28 @@ export default {
};
```

**Custom Usage**
If you want custom usage, for example, twitter-client to search the web before posting a tweet, you can also import the webSearchService and use it directly. Here's how you can do it:

```typescript
// packages/client-twitter/src/post.ts
const webSearchService = new WebSearchService();
await webSearchService.initialize(runtime);
const latestNews = await webSearchService.search(
"latest news on AI Agents",
// searchOptions
);

const state = await this.runtime.composeState(
{ } // memory,
{ // additional keys
latestNews: latestNews,
}
);

// Then modify the tweet template to include the {{latestNews}} and however you need
```

## Features

### Web Search
Expand Down
4 changes: 3 additions & 1 deletion packages/plugin-web-search/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
],
"dependencies": {
"@elizaos/core": "workspace:*",
"tsup": "8.3.5"
"@tavily/core": "^0.0.2",
"tsup": "8.3.5",
"js-tiktoken": "1.0.15"
},
"scripts": {
"build": "tsup --format esm --dts",
Expand Down
201 changes: 201 additions & 0 deletions packages/plugin-web-search/src/actions/webSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import {
Action,
HandlerCallback,
IAgentRuntime,
Memory,
State,
elizaLogger
} from "@elizaos/core";
import { encodingForModel, TiktokenModel } from "js-tiktoken";
import { WebSearchService } from "../services/webSearchService";
import { SearchResult } from "../types";

const DEFAULT_MAX_WEB_SEARCH_TOKENS = 4000;
const DEFAULT_MODEL_ENCODING = "gpt-3.5-turbo";

function getTotalTokensFromString(
str: string,
encodingName: TiktokenModel = DEFAULT_MODEL_ENCODING
) {
const encoding = encodingForModel(encodingName);
return encoding.encode(str).length;
}

function MaxTokens(
data: string,
maxTokens: number = DEFAULT_MAX_WEB_SEARCH_TOKENS
): string {
if (getTotalTokensFromString(data) >= maxTokens) {
return data.slice(0, maxTokens);
}
return data;
}

export const webSearch: Action = {
name: "WEB_SEARCH",
similes: [
"SEARCH_WEB",
"INTERNET_SEARCH",
"LOOKUP",
"QUERY_WEB",
"FIND_ONLINE",
"SEARCH_ENGINE",
"WEB_LOOKUP",
"ONLINE_SEARCH",
"FIND_INFORMATION",
],
suppressInitialMessage: true,
description:
"Perform a web search to find information related to the message.",
validate: async (runtime: IAgentRuntime, message: Memory) => {
const tavilyApiKeyOk = !!runtime.getSetting("TAVILY_API_KEY");

return tavilyApiKeyOk;
},
handler: async (
runtime: IAgentRuntime,
message: Memory,
state: State,
options: any,
callback: HandlerCallback
) => {
elizaLogger.log("Composing state for message:", message);
state = (await runtime.composeState(message)) as State;
const userId = runtime.agentId;
elizaLogger.log("User ID:", userId);

const webSearchPrompt = message.content.text;
elizaLogger.log("web search prompt received:", webSearchPrompt);

const webSearchService = new WebSearchService();
await webSearchService.initialize(runtime);
const searchResponse = await webSearchService.search(
webSearchPrompt,
);

if (searchResponse && searchResponse.results.length) {
const responseList = searchResponse.answer
? `${searchResponse.answer}${
Array.isArray(searchResponse.results) &&
searchResponse.results.length > 0
? `\n\nFor more details, you can check out these resources:\n${searchResponse.results
.map(
(result: SearchResult, index: number) =>
`${index + 1}. [${result.title}](${result.url})`
)
.join("\n")}`
: ""
}`
: "";

callback({
text: MaxTokens(responseList, DEFAULT_MAX_WEB_SEARCH_TOKENS),
});
} else {
elizaLogger.error("search failed or returned no data.");
}
},
examples: [
[
{
user: "{{user1}}",
content: {
text: "Find the latest news about SpaceX launches.",
},
},
{
user: "{{agentName}}",
content: {
text: "Here is the latest news about SpaceX launches:",
action: "WEB_SEARCH",
},
},
],
[
{
user: "{{user1}}",
content: {
text: "Can you find details about the iPhone 16 release?",
},
},
{
user: "{{agentName}}",
content: {
text: "Here are the details I found about the iPhone 16 release:",
action: "WEB_SEARCH",
},
},
],
[
{
user: "{{user1}}",
content: {
text: "What is the schedule for the next FIFA World Cup?",
},
},
{
user: "{{agentName}}",
content: {
text: "Here is the schedule for the next FIFA World Cup:",
action: "WEB_SEARCH",
},
},
],
[
{
user: "{{user1}}",
content: { text: "Check the latest stock price of Tesla." },
},
{
user: "{{agentName}}",
content: {
text: "Here is the latest stock price of Tesla I found:",
action: "WEB_SEARCH",
},
},
],
[
{
user: "{{user1}}",
content: {
text: "What are the current trending movies in the US?",
},
},
{
user: "{{agentName}}",
content: {
text: "Here are the current trending movies in the US:",
action: "WEB_SEARCH",
},
},
],
[
{
user: "{{user1}}",
content: {
text: "What is the latest score in the NBA finals?",
},
},
{
user: "{{agentName}}",
content: {
text: "Here is the latest score from the NBA finals:",
action: "WEB_SEARCH",
},
},
],
[
{
user: "{{user1}}",
content: { text: "When is the next Apple keynote event?" },
},
{
user: "{{agentName}}",
content: {
text: "Here is the information about the next Apple keynote event:",
action: "WEB_SEARCH",
},
},
],
],
} as Action;
Loading

0 comments on commit bb82372

Please sign in to comment.