-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Integrate Perplexica search as a plugin #3168
Open
boliang-pinai
wants to merge
8
commits into
elizaOS:develop
Choose a base branch
from
boliang-pinai:add_perplexica_search
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+280
−0
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
1513c99
add perplexica search
83be0d0
roll back pnpm-lock.yaml
bb850ca
small polish
4a58924
add remaining files
10fbbc1
edit readme
bd2348a
add plugin-perplexica/src
4ca4cf5
Merge branch 'develop' into add_perplexica_search
boliang-pinai 63cc113
Merge branch 'develop' into add_perplexica_search
samarth30 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# @elizaos/plugin-perplexica | ||
|
||
A plugin that integrates [Perplexica's](https://github.com/ItzCrazyKns/Perplexica) web search capabilities into Eliza agents, enabling them to access real-time information from the internet. This adapter allows agents to find and utilize up-to-date information from web pages, academic sources, and other online platforms. | ||
|
||
## Overview | ||
|
||
In the Eliza framework, when composing "context" which is the core information that an agent passes to the LLM to generate responses and decide actions, the context is constructed from static data including predefined character bios, lore, and knowledge (through RAG). By integrating the Perplexica search engine, agents gain access to a broader knowledge pool and can respond with real-time information like weather conditions, current time, stock prices, and much more. This significantly enhances the agent's ability to provide up-to-date and relevant responses beyond their static knowledge base. | ||
|
||
Perplexica search is integrated into Eliza as a plugin that adds a new service, implementing the `IPerplexicaSearchService` interface. This service is used to search the web for information relevant to the agent's current state and response. | ||
|
||
|
||
## Usage | ||
|
||
1. First, set up Perplexica search engine by following the instructions at [Perplexica Installation Guide](https://github.com/ItzCrazyKns/Perplexica?tab=readme-ov-file#installation) | ||
|
||
2. Configure the Perplexica search engine in your .env file: | ||
|
||
``` | ||
# Perplexica Configuration | ||
PERPLEXICA_API_URL= # Default: http://localhost:3001/api/search | ||
PERPLEXICA_MODEL_PROVIDER= # Default: openai | ||
PERPLEXICA_MODEL_NAME= # Default: gpt-4o-mini | ||
PERPLEXICA_EMBEDDING_MODEL_PROVIDER= # Default: openai | ||
PERPLEXICA_EMBEDDING_MODEL_NAME= # Default: text-embedding-3-large | ||
``` | ||
|
||
3. Edit the character file to enable the Perplexica search plugin: | ||
|
||
``` | ||
... | ||
|
||
"plugins": ["@elizaos/plugin-perplexica"] | ||
|
||
... | ||
``` | ||
|
||
4. Modify the client to use the Perplexica search service. For example, in the Telegram client, modify the `messageManager.ts` file to use the Perplexica search service: | ||
|
||
``` | ||
import { IPerplexicaSearchService } from "@elizaos/plugin-perplexica"; | ||
|
||
export class MessageManager { | ||
// Main handler for incoming messages | ||
public async handleMessage(ctx: Context): Promise<void> { | ||
... | ||
|
||
// Create additional state keys | ||
let stateAdditionalKeys: { [key: string]: string } = {}; | ||
|
||
// Get perplexity search result | ||
const searchResult = await this.runtime.getService<IPerplexicaSearchService>(ServiceType.PERPLEXICA_SEARCH).search( | ||
`${messageText} (says to ${this.runtime.character.name}, please reply in a short paragraph)` | ||
); | ||
stateAdditionalKeys["searchResult"] = `# Web Search Results (ignore if irrelevant)\n${searchResult.message}`; | ||
|
||
// Update state with the new memory | ||
let state = await this.runtime.composeState(memory, stateAdditionalKeys); | ||
state = await this.runtime.updateRecentMessageState(state); | ||
|
||
... | ||
} | ||
} | ||
``` | ||
|
||
5. Start the agent as usual. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"name": "@elizaos/plugin-perplexica", | ||
"version": "0.1.9", | ||
"type": "module", | ||
"main": "dist/index.js", | ||
"module": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"exports": { | ||
"./package.json": "./package.json", | ||
".": { | ||
"import": { | ||
"@elizaos/source": "./src/index.ts", | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
} | ||
} | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"dependencies": { | ||
"@elizaos/core": "workspace:*", | ||
"tsup": "8.3.5" | ||
}, | ||
"scripts": { | ||
"build": "tsup --format esm --dts", | ||
"dev": "tsup --format esm --dts --watch", | ||
"lint": "eslint --fix --cache ." | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { | ||
Plugin | ||
} from "@elizaos/core"; | ||
import { PerplexicaSearchService } from "./search_service"; | ||
|
||
export const PerplexicaSearchPlugin: Plugin = { | ||
name: "perplexicaSearch", | ||
description: "Search the web with Perplexica search engine", | ||
services: [new PerplexicaSearchService()], | ||
}; | ||
|
||
export default PerplexicaSearchPlugin; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import { | ||
Memory, | ||
Actor, | ||
elizaLogger, | ||
Character, | ||
Service, | ||
IAgentRuntime, | ||
ServiceType | ||
} from "@elizaos/core"; | ||
|
||
export interface IPerplexicaSearchService extends Service { | ||
settings: { | ||
[key: string]: string; | ||
}; | ||
search( | ||
query: string, | ||
messages?: Memory[], | ||
actors?: Actor[], | ||
character?: Character, | ||
optimizationMode?: string, | ||
focusMode?: string, | ||
): Promise<PerplexicaSearchResponse>; | ||
} | ||
|
||
|
||
export class PerplexicaSearchService extends Service implements IPerplexicaSearchService { | ||
settings: {[key: string]: string;}; | ||
|
||
static get serviceType(): ServiceType { | ||
return ServiceType.PERPLEXICA_SEARCH; | ||
} | ||
|
||
async initialize(runtime: IAgentRuntime): Promise<void> { | ||
this.settings = { | ||
modelProvider: runtime.getSetting('PERPLEXICA_MODEL_PROVIDER') || 'openai', | ||
modelName: runtime.getSetting('PERPLEXICA_MODEL_NAME') || 'gpt-4o-mini', | ||
embeddingModelProvider: runtime.getSetting('PERPLEXICA_EMBEDDING_MODEL_PROVIDER') || 'openai', | ||
embeddingModelName: runtime.getSetting('PERPLEXICA_EMBEDDING_MODEL_NAME') || 'text-embedding-3-large', | ||
apiUrl: runtime.getSetting('PERPLEXICA_API_URL') || 'http://localhost:3001/api/search', | ||
} | ||
} | ||
|
||
async search( | ||
query: string, | ||
messages?: Memory[], | ||
actors?: Actor[], | ||
character?: Character, | ||
optimizationMode: 'speed' | 'balanced' | 'quality' = 'speed', | ||
focusMode: 'webSearch' | 'academicSearch' | 'writingAssistant' | 'wolframAlphaSearch' | 'youtubeSearch' | 'redditSearch' = 'webSearch', | ||
): Promise<PerplexicaSearchResponse> { | ||
const history = formatPerplexicaSearchHistory(messages, actors, character?.name); | ||
|
||
elizaLogger.debug("Searching with Perplexica:\n", | ||
query, history, this.settings.optimizationMode, this.settings.focusMode); | ||
|
||
try { | ||
const searchRequest: SearchRequest = { | ||
chatModel: { | ||
provider: this.settings.modelProvider, | ||
model: this.settings.modelName, | ||
}, | ||
embeddingModel: { | ||
provider: this.settings.embeddingModelProvider, | ||
model: this.settings.embeddingModelName, | ||
}, | ||
optimizationMode: optimizationMode, | ||
focusMode: focusMode, | ||
query, | ||
history: history || [] | ||
}; | ||
elizaLogger.debug('Search request:', searchRequest); | ||
|
||
const response = await fetch(this.settings.apiUrl, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
'Accept': 'application/json' | ||
}, | ||
body: JSON.stringify(searchRequest), | ||
}); | ||
|
||
if (!response.ok) { | ||
const errorText = await response.text(); | ||
elizaLogger.error('Response error:', errorText); | ||
throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`); | ||
} | ||
|
||
const data = await response.json(); | ||
elizaLogger.debug('Search response:', data); | ||
return data; | ||
} catch (error) { | ||
elizaLogger.error('Error searching Perplexica:', error); | ||
return { | ||
message: 'Unknown error occurred', | ||
sources: [] | ||
}; | ||
} | ||
} | ||
} | ||
|
||
interface ChatModel { | ||
provider: string; | ||
model: string; | ||
} | ||
|
||
interface SearchRequest { | ||
chatModel: ChatModel; | ||
embeddingModel: ChatModel; | ||
optimizationMode: string; | ||
focusMode: string; | ||
query: string; | ||
history?: [string, string][]; | ||
} | ||
|
||
export interface PerplexicaSearchResponse { | ||
message: string; | ||
sources: { | ||
pageContent: string; | ||
metadata: { | ||
title: string; | ||
url: string; | ||
}; | ||
}[]; | ||
} | ||
|
||
function formatPerplexicaSearchHistory( | ||
messages: Memory[], | ||
actors: Actor[], | ||
agentName: string, | ||
): [string, string][] { | ||
return messages | ||
.slice(0, 6) // limit to 6 messages | ||
.reverse() | ||
.filter((message) => message.userId) | ||
.map((message) => { | ||
const messageContent = message.content.text; | ||
const formattedName = | ||
actors.find((actor) => actor.id === message.userId)?.name === agentName | ||
? "assistant" | ||
: "human"; | ||
|
||
return [formattedName, messageContent]; | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"extends": "../core/tsconfig.json", | ||
"compilerOptions": { | ||
"outDir": "dist", | ||
"rootDir": "src", | ||
"types": ["node"] | ||
}, | ||
"include": ["src/**/*.ts"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { defineConfig } from "tsup"; | ||
|
||
export default defineConfig({ | ||
entry: ["src/index.ts"], | ||
outDir: "dist", | ||
sourcemap: true, | ||
clean: true, | ||
format: ["esm"], | ||
external: ["dotenv", "fs", "path", "https", "http", "agentkeepalive"], | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The debug log references
this.settings.optimizationMode
andthis.settings.focusMode
, but these properties don't exist in thesettings
object. The log should use the function parametersoptimizationMode
andfocusMode
directly since they contain the actual values being used in the search.Spotted by Graphite Reviewer
Is this helpful? React 👍 or 👎 to let us know.