mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
added perplexity tool (#129)
This commit is contained in:
@@ -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',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}`,
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import { chatTool } from './chat'
|
||||
|
||||
export const perplexityChatTool = chatTool
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user