mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat(memory): added pinecone block/tools
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
import { PineconeIcon } from '@/components/icons'
|
||||
// You'll need to create this icon
|
||||
import { PineconeResponse } from '@/tools/pinecone/types'
|
||||
import { BlockConfig } from '../types'
|
||||
|
||||
export const PineconeBlock: BlockConfig<PineconeResponse> = {
|
||||
type: 'pinecone',
|
||||
name: 'Pinecone',
|
||||
description: 'Interact with Pinecone vector database',
|
||||
category: 'tools',
|
||||
bgColor: '#0D1117',
|
||||
icon: PineconeIcon,
|
||||
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'operation',
|
||||
title: 'Operation',
|
||||
type: 'dropdown',
|
||||
layout: 'full',
|
||||
options: [
|
||||
{ label: 'Query', id: 'query' },
|
||||
{ label: 'Upsert', id: 'upsert' },
|
||||
{ label: 'Delete', id: 'delete' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'apiKey',
|
||||
title: 'API Key',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Your Pinecone API key',
|
||||
password: true,
|
||||
},
|
||||
{
|
||||
id: 'environment',
|
||||
title: 'Environment',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'gcp-starter',
|
||||
},
|
||||
{
|
||||
id: 'indexName',
|
||||
title: 'Index Name',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'my-index',
|
||||
},
|
||||
// Query operation fields
|
||||
{
|
||||
id: 'queryVector',
|
||||
title: 'Query Vector',
|
||||
type: 'long-input',
|
||||
layout: 'full',
|
||||
placeholder: '[0.1, 0.2, 0.3, ...]',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
},
|
||||
{
|
||||
id: 'topK',
|
||||
title: 'Top K Results',
|
||||
type: 'short-input',
|
||||
layout: 'half',
|
||||
placeholder: '10',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
},
|
||||
{
|
||||
id: 'includeMetadata',
|
||||
title: 'Include Metadata',
|
||||
type: 'switch',
|
||||
layout: 'half',
|
||||
value: () => 'true',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
},
|
||||
{
|
||||
id: 'includeValues',
|
||||
title: 'Include Values',
|
||||
type: 'switch',
|
||||
layout: 'half',
|
||||
value: () => 'false',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
},
|
||||
// Upsert operation fields
|
||||
{
|
||||
id: 'vectors',
|
||||
title: 'Vectors',
|
||||
type: 'long-input',
|
||||
layout: 'full',
|
||||
placeholder: '[{"id": "vec1", "values": [0.1, 0.2, 0.3], "metadata": {"key": "value"}}]',
|
||||
condition: { field: 'operation', value: 'upsert' },
|
||||
},
|
||||
// Delete operation fields
|
||||
{
|
||||
id: 'ids',
|
||||
title: 'Vector IDs',
|
||||
type: 'long-input',
|
||||
layout: 'full',
|
||||
placeholder: '["vec1", "vec2", ...]',
|
||||
condition: { field: 'operation', value: 'delete' },
|
||||
},
|
||||
{
|
||||
id: 'deleteAll',
|
||||
title: 'Delete All Vectors',
|
||||
type: 'switch',
|
||||
layout: 'half',
|
||||
value: () => 'false',
|
||||
condition: { field: 'operation', value: 'delete' },
|
||||
},
|
||||
],
|
||||
|
||||
tools: {
|
||||
access: ['pinecone_query', 'pinecone_upsert', 'pinecone_delete'],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
switch (params.operation) {
|
||||
case 'query':
|
||||
return 'pinecone_query'
|
||||
case 'upsert':
|
||||
return 'pinecone_upsert'
|
||||
case 'delete':
|
||||
return 'pinecone_delete'
|
||||
default:
|
||||
throw new Error('Invalid operation selected')
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
inputs: {
|
||||
operation: { type: 'string', required: true },
|
||||
apiKey: { type: 'string', required: true },
|
||||
environment: { type: 'string', required: true },
|
||||
indexName: { type: 'string', required: true },
|
||||
// Query operation inputs
|
||||
queryVector: { type: 'json', required: false },
|
||||
topK: { type: 'number', required: false },
|
||||
includeMetadata: { type: 'boolean', required: false },
|
||||
includeValues: { type: 'boolean', required: false },
|
||||
// Upsert operation inputs
|
||||
vectors: { type: 'json', required: false },
|
||||
// Delete operation inputs
|
||||
ids: { type: 'json', required: false },
|
||||
deleteAll: { type: 'boolean', required: false },
|
||||
},
|
||||
|
||||
outputs: {
|
||||
response: {
|
||||
type: {
|
||||
matches: 'any',
|
||||
upsertedCount: 'any',
|
||||
deletedCount: 'any',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import { GitHubBlock } from './blocks/github'
|
||||
import { GmailBlock } from './blocks/gmail'
|
||||
import { JinaBlock } from './blocks/jina'
|
||||
import { NotionBlock } from './blocks/notion'
|
||||
import { PineconeBlock } from './blocks/pinecone'
|
||||
import { RouterBlock } from './blocks/router'
|
||||
import { SerperBlock } from './blocks/serper'
|
||||
import { SlackBlock } from './blocks/slack'
|
||||
@@ -41,6 +42,7 @@ export {
|
||||
GmailBlock,
|
||||
XBlock,
|
||||
StarterBlock,
|
||||
PineconeBlock,
|
||||
}
|
||||
|
||||
// Registry of all block configurations
|
||||
@@ -64,6 +66,7 @@ const blocks: Record<string, BlockConfig> = {
|
||||
notion: NotionBlock,
|
||||
gmail: GmailBlock,
|
||||
x: XBlock,
|
||||
pinecone: PineconeBlock,
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
|
||||
@@ -1388,3 +1388,23 @@ export function StartIcon(props: SVGProps<SVGSVGElement>) {
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function PineconeIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
width="256px"
|
||||
height="288px"
|
||||
viewBox="0 0 256 288"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
preserveAspectRatio="xMidYMid"
|
||||
>
|
||||
<path
|
||||
d="M108.633615,254.43629 C117.713862,254.43629 125.074857,261.797284 125.074857,270.877532 C125.074857,279.957779 117.713862,287.318774 108.633615,287.318774 C99.5533677,287.318774 92.1923728,279.957779 92.1923728,270.877532 C92.1923728,261.797284 99.5533677,254.43629 108.633615,254.43629 Z M199.849665,224.438339 L216.09705,229.252379 L203.199913,272.780219 C202.072982,276.58361 198.458049,279.095992 194.500389,278.826397 L190.516677,278.552973 L190.419263,278.633409 L149.02918,275.728903 L150.180842,258.822508 L177.989056,260.709686 L159.783784,234.447622 L173.709616,224.792379 L191.938895,251.08702 L199.849665,224.438339 Z M23.0126771,194.347476 L39.9158866,195.544979 L37.935897,223.348728 L64.1501315,205.120082 L73.8271476,219.030793 L47.578736,237.278394 L74.3707554,245.173037 L69.5818063,261.427835 L25.8485266,248.543243 C22.0304448,247.418369 19.5101155,243.787479 19.7913963,239.817092 L23.0126771,194.347476 Z M132.151306,170.671396 L162.658679,207.503468 L148.909247,218.891886 L130.753266,196.972134 L124.866941,230.673893 L107.280249,227.599613 L113.172232,193.845272 L88.7296311,208.256891 L79.6674587,192.874434 L120.745504,168.674377 C124.522104,166.449492 129.355297,167.295726 132.151306,170.671396 Z M217.504528,145.960198 L232.744017,137.668804 L254.94482,178.473633 C256.889641,182.048192 256.088221,186.494171 253.017682,189.164674 L249.876622,191.878375 L217.826246,219.77131 L206.441034,206.680621 L227.988588,187.934494 L195.893546,182.152609 L198.972402,165.078949 L231.044844,170.857793 L217.504528,145.960198 Z M37.7821805,103.299272 L49.2622123,116.306888 L28.0106317,135.050179 L60.1668233,140.664193 L57.1863573,157.755303 L24.9947229,152.136967 L38.822104,177.134576 L23.6411026,185.532577 L1.08439616,144.756992 C-0.885025494,141.196884 -0.115545265,136.746375 2.93488097,134.054184 L37.7821805,103.299272 Z M146.476311,89.8796828 L176.88045,126.612847 L163.1271,137.996532 L144.975445,116.067101 L139.08912,149.778947 L121.502428,146.704666 L127.374238,113.081452 L103.025237,127.354817 L93.9976317,111.952048 L131.398812,90.0233663 L131.435631,89.880899 L131.600545,89.9023265 L135.085833,87.870141 C138.861877,85.6569913 143.68556,86.5079996 146.476311,89.8796828 Z M185.655786,71.8143168 L192.305535,55.7902703 L235.318239,73.6399229 C239.072486,75.1978811 241.2415,79.1537636 240.536356,83.1568091 L239.820231,87.1385839 L232.47517,128.919545 L215.389188,125.909819 L220.312646,97.9413879 L191.776157,113.7129 L183.390302,98.5251862 L211.981072,82.7408038 L185.655786,71.8143168 Z M103.71696,40.2373824 L104.456513,57.5706533 L76.0432671,58.785006 L97.4730368,83.2749086 L84.4165529,94.6993319 L62.9507932,70.1728358 L57.949673,98.1737132 L40.8716575,95.1191088 L49.0561498,49.3603563 C49.771444,45.3612115 53.1664633,42.3942036 57.2253811,42.2210231 L61.246149,42.0411642 L61.3363168,41.9758 L103.71696,40.2373824 Z M161.838155,3.27194826 L192.104824,40.2369789 L178.291207,51.5474574 L160.327329,29.6043227 L154.268381,63.2715157 L136.697231,60.1096121 L142.766468,26.3665075 L118.24002,40.7062765 L109.232678,25.2916494 L150.427675,1.21987397 C154.218286,-0.995121237 159.056796,-0.124957814 161.838155,3.27194826 Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@ import { readUrlTool } from './jina/reader'
|
||||
import { notionReadTool } from './notion/read'
|
||||
import { notionWriteTool } from './notion/write'
|
||||
import { chatTool as openAIChat } from './openai/chat'
|
||||
import { deleteTool as pineconeDeleteTool } from './pinecone/delete'
|
||||
import { queryTool as pineconeQueryTool } from './pinecone/query'
|
||||
import { upsertTool as pineconeUpsertTool } from './pinecone/upsert'
|
||||
import { opportunitiesTool as salesforceOpportunities } from './salesforce/opportunities'
|
||||
import { searchTool as serperSearch } from './serper/search'
|
||||
import { slackMessageTool } from './slack/message'
|
||||
@@ -58,6 +61,9 @@ export const tools: Record<string, ToolConfig> = {
|
||||
x_read: xRead,
|
||||
x_search: xSearch,
|
||||
x_user: xUser,
|
||||
pinecone_query: pineconeQueryTool,
|
||||
pinecone_upsert: pineconeUpsertTool,
|
||||
pinecone_delete: pineconeDeleteTool,
|
||||
}
|
||||
|
||||
// Get a tool by its ID
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { ToolConfig } from '../types'
|
||||
import { PineconeParams, PineconeResponse } from './types'
|
||||
|
||||
export const deleteTool: ToolConfig<PineconeParams, PineconeResponse> = {
|
||||
id: 'pinecone_delete',
|
||||
name: 'Pinecone Delete',
|
||||
description: 'Delete vectors from Pinecone index',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
apiKey: { type: 'string', required: true, description: 'Pinecone API key' },
|
||||
environment: { type: 'string', required: true, description: 'Pinecone environment' },
|
||||
indexName: { type: 'string', required: true, description: 'Name of the Pinecone index' },
|
||||
ids: { type: 'array', required: false, description: 'Array of vector IDs to delete' },
|
||||
deleteAll: { type: 'boolean', required: false, description: 'Delete all vectors in the index' },
|
||||
},
|
||||
|
||||
request: {
|
||||
method: 'POST',
|
||||
url: (params) =>
|
||||
`https://${params.indexName}-${params.environment}.svc.${params.environment}.pinecone.io/vectors/delete`,
|
||||
headers: (params) => ({
|
||||
'Api-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => ({
|
||||
ids: params.ids,
|
||||
deleteAll: params.deleteAll,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
deletedCount: response.ok ? 1 : 0, // Pinecone doesn't return count, so we estimate
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
transformError: (error) => `Pinecone delete failed: ${error.message}`,
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import { ToolConfig } from '../types'
|
||||
import { PineconeParams, PineconeResponse } from './types'
|
||||
|
||||
export const queryTool: ToolConfig<PineconeParams, PineconeResponse> = {
|
||||
id: 'pinecone_query',
|
||||
name: 'Pinecone Query',
|
||||
description: 'Query vectors from Pinecone index',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
apiKey: { type: 'string', required: true, description: 'Pinecone API key' },
|
||||
environment: { type: 'string', required: true, description: 'Pinecone environment' },
|
||||
indexName: { type: 'string', required: true, description: 'Name of the Pinecone index' },
|
||||
queryVector: { type: 'array', required: true, description: 'Vector to query' },
|
||||
topK: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
default: 10,
|
||||
description: 'Number of results to return',
|
||||
},
|
||||
includeMetadata: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
default: true,
|
||||
description: 'Include metadata in results',
|
||||
},
|
||||
includeValues: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
default: false,
|
||||
description: 'Include vector values in results',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
method: 'POST',
|
||||
url: (params) =>
|
||||
`https://${params.indexName}-${params.environment}.svc.${params.environment}.pinecone.io/vectors/query`,
|
||||
headers: (params) => ({
|
||||
'Api-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => ({
|
||||
vector: params.queryVector,
|
||||
topK: params.topK || 10,
|
||||
includeMetadata: params.includeMetadata ?? true,
|
||||
includeValues: params.includeValues ?? false,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
matches: data.matches || [],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
transformError: (error) => `Pinecone query failed: ${error.message}`,
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { ToolResponse } from '../types'
|
||||
|
||||
export interface PineconeParams {
|
||||
apiKey: string
|
||||
environment: string
|
||||
indexName: string
|
||||
operation: 'query' | 'upsert' | 'delete'
|
||||
// Query operation
|
||||
queryVector?: number[]
|
||||
topK?: number
|
||||
includeMetadata?: boolean
|
||||
includeValues?: boolean
|
||||
// Upsert operation
|
||||
vectors?: Array<{
|
||||
id: string
|
||||
values: number[]
|
||||
metadata?: Record<string, any>
|
||||
}>
|
||||
// Delete operation
|
||||
ids?: string[]
|
||||
deleteAll?: boolean
|
||||
}
|
||||
|
||||
export interface PineconeResponse extends ToolResponse {
|
||||
output: {
|
||||
matches?: Array<{
|
||||
id: string
|
||||
score: number
|
||||
values?: number[]
|
||||
metadata?: Record<string, any>
|
||||
}>
|
||||
upsertedCount?: number
|
||||
deletedCount?: number
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { ToolConfig } from '../types'
|
||||
import { PineconeParams, PineconeResponse } from './types'
|
||||
|
||||
export const upsertTool: ToolConfig<PineconeParams, PineconeResponse> = {
|
||||
id: 'pinecone_upsert',
|
||||
name: 'Pinecone Upsert',
|
||||
description: 'Upsert vectors into Pinecone index',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
apiKey: { type: 'string', required: true, description: 'Pinecone API key' },
|
||||
environment: { type: 'string', required: true, description: 'Pinecone environment' },
|
||||
indexName: { type: 'string', required: true, description: 'Name of the Pinecone index' },
|
||||
vectors: {
|
||||
type: 'array',
|
||||
required: true,
|
||||
description: 'Array of vectors to upsert, each with id, values, and optional metadata',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
method: 'POST',
|
||||
url: (params) =>
|
||||
`https://${params.indexName}-${params.environment}.svc.${params.environment}.pinecone.io/vectors/upsert`,
|
||||
headers: (params) => ({
|
||||
'Api-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => ({
|
||||
vectors: params.vectors,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
upsertedCount: data.upsertedCount || 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
transformError: (error) => `Pinecone upsert failed: ${error.message}`,
|
||||
}
|
||||
Reference in New Issue
Block a user