Added translate block, added ability to add default value during block definition

This commit is contained in:
Waleed Latif
2025-01-31 18:08:24 -08:00
parent 6293874be2
commit b7aa70b87f
6 changed files with 160 additions and 2 deletions

View File

@@ -15,6 +15,10 @@ interface SubBlockProps {
}
export function SubBlock({ blockId, config, isConnecting }: SubBlockProps) {
if (config.hidden) {
return null
}
const handleMouseDown = (e: React.MouseEvent) => {
e.stopPropagation()
}

110
blocks/blocks/translate.ts Normal file
View File

@@ -0,0 +1,110 @@
import { TranslateIcon } from '@/components/icons'
import { BlockConfig } from '../types'
import { ChatResponse } from '@/tools/openai/chat'
const MODEL_TOOLS = {
'gpt-4o': 'openai.chat',
'o1': 'openai.chat',
'o1-mini': 'openai.chat',
'claude-3-5-sonnet-20241022': 'anthropic.chat',
'gemini-pro': 'google.chat',
} as const
const getTranslationPrompt = (targetLanguage: string) => `You are a highly skilled translator. Your task is to translate the given text into ${targetLanguage || 'English'} while:
1. Preserving the original meaning and nuance
2. Maintaining appropriate formality levels
3. Adapting idioms and cultural references appropriately
4. Preserving formatting and special characters
5. Handling technical terms accurately
Only return the translated text without any explanations or notes. The translation should be natural and fluent in ${targetLanguage || 'English'}.`
export const TranslateBlock: BlockConfig<ChatResponse> = {
type: 'translate',
toolbar: {
title: 'Translate',
description: 'Translate text to any language',
bgColor: '#FF4B4B',
icon: TranslateIcon,
category: 'basic',
},
tools: {
access: ['openai.chat', 'anthropic.chat', 'google.chat'],
config: {
tool: (params: Record<string, any>) => {
const model = params.model || 'gpt-4o'
if (!model) {
throw new Error('No model selected')
}
const tool = MODEL_TOOLS[model as keyof typeof MODEL_TOOLS]
if (!tool) {
throw new Error(`Invalid model selected: ${model}`)
}
return tool
}
}
},
workflow: {
inputs: {
context: { type: 'string', required: true },
targetLanguage: { type: 'string', required: true },
apiKey: { type: 'string', required: true },
systemPrompt: { type: 'string', required: true }
},
outputs: {
response: {
type: {
content: 'string',
model: 'string',
tokens: 'any'
}
}
},
subBlocks: [
{
id: 'context',
title: 'Text to Translate',
type: 'long-input',
layout: 'full',
placeholder: 'Enter the text you want to translate'
},
{
id: 'targetLanguage',
title: 'Translate To',
type: 'short-input',
layout: 'full',
placeholder: 'Enter language (e.g. Spanish, French, etc.)'
},
{
id: 'model',
title: 'Model',
type: 'dropdown',
layout: 'half',
options: Object.keys(MODEL_TOOLS)
},
{
id: 'apiKey',
title: "API Key",
type: "short-input",
layout: "full",
placeholder: "Enter your API key",
password: true,
connectionDroppable: false
},
{
id: 'systemPrompt',
title: 'System Prompt',
type: 'code',
layout: 'full',
hidden: true,
value: (params: Record<string, any>) => {
return getTranslationPrompt(params.targetLanguage || 'English')
}
}
]
}
}

View File

@@ -7,6 +7,7 @@ import { FunctionBlock } from './blocks/function'
import { CrewAIVisionBlock } from './blocks/crewai'
import { FirecrawlScrapeBlock } from './blocks/firecrawl'
import { JinaBlock } from './blocks/jina'
import { TranslateBlock } from './blocks/translate'
// Export blocks for ease of use
export {
@@ -15,7 +16,8 @@ export {
FunctionBlock,
CrewAIVisionBlock,
FirecrawlScrapeBlock,
JinaBlock
JinaBlock,
TranslateBlock
}
// Registry of all block configurations
@@ -25,7 +27,8 @@ const blocks: Record<string, BlockConfig> = {
function: FunctionBlock,
crewai_vision: CrewAIVisionBlock,
firecrawl_scrape: FirecrawlScrapeBlock,
jina_reader: JinaBlock
jina_reader: JinaBlock,
translate: TranslateBlock
}
// Build a reverse mapping of tools to block types

View File

@@ -46,6 +46,8 @@ export interface SubBlockConfig {
placeholder?: string
password?: boolean
connectionDroppable?: boolean
hidden?: boolean
value?: (params: Record<string, any>) => string
}
export interface BlockConfig<T extends ToolResponse = ToolResponse> {

View File

@@ -956,3 +956,25 @@ export function JinaAIIcon(props: SVGProps<SVGSVGElement>) {
</svg>
)
}
export const TranslateIcon = (props: SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
{...props}
>
<path d="m5 8 6 6" />
<path d="m4 14 6-6 2-3" />
<path d="M2 5h12" />
<path d="M7 2h1" />
<path d="m22 22-5-10-5 10" />
<path d="M14 18h6" />
</svg>
)

View File

@@ -58,10 +58,27 @@ export class Serializer {
}
private extractParams(block: BlockState): Record<string, any> {
const blockConfig = getBlock(block.type)
if (!blockConfig) {
throw new Error(`Invalid block type: ${block.type}`)
}
const params: Record<string, any> = {}
// First collect all current values from subBlocks
Object.entries(block.subBlocks).forEach(([id, subBlock]) => {
params[id] = subBlock.value
})
// Then check for any subBlocks with default values
blockConfig.workflow.subBlocks.forEach(subBlockConfig => {
const id = subBlockConfig.id
if (params[id] === null && subBlockConfig.value) {
// If the value is null and there's a default value function, use it
params[id] = subBlockConfig.value(params)
}
})
return params
}