added perplexity tool (#129)

This commit is contained in:
Waleed Latif
2025-03-20 14:29:55 -07:00
committed by GitHub
parent df0b2d2d2d
commit a12f234a71
6 changed files with 291 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
import { PerplexityIcon } from '@/components/icons'
import { ToolResponse } from '@/tools/types'
import { BlockConfig } from '../types'
interface PerplexityChatResponse extends ToolResponse {
output: {
content: string
model: string
usage: {
prompt_tokens: number
completion_tokens: number
total_tokens: number
}
}
}
export const PerplexityBlock: BlockConfig<PerplexityChatResponse> = {
type: 'perplexity',
name: 'Perplexity',
description: 'Use Perplexity AI chat models',
longDescription:
'Generate completions using Perplexity AI models with real-time knowledge and search capabilities. Create responses, answer questions, and generate content with customizable parameters.',
category: 'tools',
bgColor: '#20808D', // Perplexity turquoise color
icon: PerplexityIcon,
subBlocks: [
{
id: 'system',
title: 'System Prompt',
type: 'long-input',
layout: 'full',
placeholder: 'Optional system prompt to guide the model behavior...',
},
{
id: 'prompt',
title: 'User Prompt',
type: 'long-input',
layout: 'full',
placeholder: 'Enter your prompt here...',
},
{
id: 'model',
title: 'Model',
type: 'dropdown',
layout: 'half',
options: [
{ label: 'Sonar', id: 'sonar' },
{ label: 'Mistral', id: 'mistral' },
{ label: 'Claude-3-Opus', id: 'claude-3-opus' },
{ label: 'Claude-3-Sonnet', id: 'claude-3-sonnet' },
{ label: 'Command-R', id: 'command-r' },
{ label: 'GPT-4o', id: 'gpt-4o' },
],
value: () => 'sonar',
},
{
id: 'temperature',
title: 'Temperature',
type: 'slider',
layout: 'half',
min: 0,
max: 1,
value: () => '0.7',
},
{
id: 'max_tokens',
title: 'Max Tokens',
type: 'short-input',
layout: 'half',
placeholder: 'Maximum number of tokens',
},
{
id: 'apiKey',
title: 'API Key',
type: 'short-input',
layout: 'full',
placeholder: 'Enter your Perplexity API key',
password: true,
},
],
tools: {
access: ['perplexity_chat'],
config: {
tool: () => 'perplexity_chat',
params: (params) => {
const toolParams = {
apiKey: params.apiKey,
model: params.model,
prompt: params.prompt,
system: params.system,
max_tokens: params.max_tokens ? parseInt(params.max_tokens) : undefined,
temperature: params.temperature ? parseFloat(params.temperature) : undefined,
}
return toolParams
},
},
},
inputs: {
prompt: { type: 'string', required: true },
system: { type: 'string', required: false },
model: { type: 'string', required: true },
max_tokens: { type: 'string', required: false },
temperature: { type: 'string', required: false },
apiKey: { type: 'string', required: true },
},
outputs: {
response: {
type: {
content: 'string',
model: 'string',
usage: 'json',
},
},
},
}
+3
View File
@@ -14,6 +14,7 @@ import { GuestyBlock } from './blocks/guesty'
import { JinaBlock } from './blocks/jina'
import { NotionBlock } from './blocks/notion'
import { OpenAIBlock } from './blocks/openai'
import { PerplexityBlock } from './blocks/perplexity'
import { PineconeBlock } from './blocks/pinecone'
import { RedditBlock } from './blocks/reddit'
import { RouterBlock } from './blocks/router'
@@ -61,6 +62,7 @@ export {
GoogleDocsBlock,
WhatsAppBlock,
GoogleSheetsBlock,
PerplexityBlock,
}
// Registry of all block configurations, alphabetically sorted
@@ -81,6 +83,7 @@ const blocks: Record<string, BlockConfig> = {
jina: JinaBlock,
notion: NotionBlock,
openai: OpenAIBlock,
perplexity: PerplexityBlock,
pinecone: PineconeBlock,
reddit: RedditBlock,
router: RouterBlock,
+2
View File
@@ -14,6 +14,7 @@ import { contactsTool as hubspotContacts } from './hubspot/contacts'
import { readUrlTool } from './jina/reader'
import { notionReadTool, notionWriteTool } from './notion'
import { embeddingsTool as openAIEmbeddings } from './openai/embeddings'
import { perplexityChatTool } from './perplexity'
import {
pineconeFetchTool,
pineconeGenerateEmbeddingsTool,
@@ -90,6 +91,7 @@ export const tools: Record<string, ToolConfig> = {
google_sheets_update: sheetsUpdateTool,
guesty_reservation: guestyReservationTool,
guesty_guest: guestyGuestTool,
perplexity_chat: perplexityChatTool,
}
// Get a tool by its ID
+138
View File
@@ -0,0 +1,138 @@
import { ToolConfig } from '../types'
import { PerplexityChatParams, PerplexityChatResponse } from './types'
export const chatTool: ToolConfig<PerplexityChatParams, PerplexityChatResponse> = {
id: 'perplexity_chat',
name: 'Perplexity Chat',
description: 'Generate completions using Perplexity AI chat models',
version: '1.0',
params: {
apiKey: {
type: 'string',
required: true,
requiredForToolCall: true,
description: 'Perplexity API key',
},
model: {
type: 'string',
required: true,
description: 'Model to use for chat completions (e.g., sonar, mistral)',
},
messages: {
type: 'array',
required: true,
description: 'Array of message objects with role and content',
},
max_tokens: {
type: 'number',
required: false,
description: 'Maximum number of tokens to generate',
},
temperature: {
type: 'number',
required: false,
description: 'Sampling temperature between 0 and 1',
},
},
request: {
method: 'POST',
url: () => 'https://api.perplexity.ai/chat/completions',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
body: (params) => {
let messages = params.messages
if (!messages && (params.prompt || params.system)) {
messages = []
// Add system message if provided
if (params.system && typeof params.system === 'string' && params.system.trim() !== '') {
messages.push({
role: 'system',
content: params.system,
})
}
// Add user message
if (params.prompt && typeof params.prompt === 'string' && params.prompt.trim() !== '') {
messages.push({
role: 'user',
content: params.prompt,
})
}
}
// Validate that each message has role and content
for (const msg of messages!) {
if (!msg.role || !msg.content) {
throw new Error('Each message must have role and content properties')
}
}
const body: Record<string, any> = {
model: params.model,
messages: messages,
}
if (params.max_tokens !== undefined) {
body.max_tokens = params.max_tokens
}
if (params.temperature !== undefined) {
body.temperature = params.temperature
}
return body
},
},
transformResponse: async (response, params) => {
try {
// Check if the response was successful
if (!response.ok) {
const errorData = await response.json().catch(() => null)
console.error('Perplexity API error:', {
status: response.status,
statusText: response.statusText,
errorData,
})
const errorMessage = errorData
? JSON.stringify(errorData)
: `API error: ${response.status} ${response.statusText}`
throw new Error(errorMessage)
}
const data = await response.json()
// Validate response structure
if (!data.choices || !data.choices[0] || !data.choices[0].message) {
console.error('Invalid Perplexity response format:', data)
throw new Error('Invalid response format from Perplexity API')
}
return {
success: true,
output: {
content: data.choices[0].message.content,
model: data.model,
usage: {
prompt_tokens: data.usage.prompt_tokens,
completion_tokens: data.usage.completion_tokens,
total_tokens: data.usage.total_tokens,
},
},
}
} catch (error: any) {
console.error('Failed to process Perplexity response:', error)
throw error
}
},
transformError: (error) => `Perplexity chat completion failed: ${error.message}`,
}
+3
View File
@@ -0,0 +1,3 @@
import { chatTool } from './chat'
export const perplexityChatTool = chatTool
+29
View File
@@ -0,0 +1,29 @@
import { ToolResponse } from '../types'
export interface PerplexityMessage {
role: string
content: string
}
export interface PerplexityChatParams {
apiKey: string
model: string
messages?: PerplexityMessage[]
max_tokens?: number
temperature?: number
prompt?: string
system?: string
}
export interface PerplexityChatResponse extends ToolResponse {
output: {
content: string
model: string
usage: {
prompt_tokens: number
completion_tokens: number
total_tokens: number
}
}
}