Files
OllaHub/lib/prompts/mcp-tools-prompt.ts
T
Evandro Fonseca Junior f96d4ed696 refactor(api): remove MCP marketplace cache integration
Removed dependencies on MCPCacheRepository and PulseMCPService from MCP routes to simplify installation and listing logic, avoiding reliance on potentially stale cached data and streamlining the codebase. Updated available-for-chat filter to include MCPs without explicit status.
2025-10-29 15:35:15 -03:00

243 lines
6.8 KiB
TypeScript

/**
* Templates de prompt engineering para modelos sem suporte nativo a function calling
*/
import type { MCPTool } from "@/lib/types/mcp-chat";
/**
* Gera prompt de instruções para uso de tools via prompt engineering
* @param tools Array de tools disponíveis
* @returns String com instruções formatadas
*/
export function generateToolsPrompt(tools: MCPTool[]): string {
if (tools.length === 0) {
return "";
}
const toolsDescription = tools
.map((tool, index) => {
const params = Object.entries(tool.inputSchema.properties || {})
.map(([name, schema]: [string, any]) => {
const required = tool.inputSchema.required?.includes(name)
? " (required)"
: " (optional)";
const type = schema.type || "any";
const desc = schema.description || "";
return ` - ${name}: ${type}${required}${desc ? ` - ${desc}` : ""}`;
})
.join("\n");
return `${index + 1}. **${tool.name}**
Description: ${tool.description}
Parameters:
${params || " (no parameters)"}`;
})
.join("\n\n");
return `
# FERRAMENTAS DISPONÍVEIS
Você tem acesso às seguintes ferramentas externas para auxiliar o usuário:
${toolsDescription}
## INSTRUÇÕES IMPORTANTES
1. **Quando usar ferramentas:**
- Use ferramentas quando precisar de informações em tempo real
- Use ferramentas quando precisar executar ações externas
- Use ferramentas quando o usuário solicitar dados específicos
2. **Como usar ferramentas:**
- Para chamar uma ferramenta, responda EXATAMENTE no seguinte formato JSON:
\`\`\`json
{
"tool_call": {
"name": "nome_da_ferramenta",
"parameters": {
"parametro1": "valor1",
"parametro2": "valor2"
}
}
}
\`\`\`
- NÃO adicione texto antes ou depois do JSON
- Certifique-se de que o JSON está bem formatado
- Use apenas ferramentas da lista acima
3. **REGRA CRUCIAL - NUNCA MENCIONE AO USUÁRIO:**
- NUNCA mencione que você está usando ferramentas
- NUNCA mencione MCPs ou APIs externas
- NUNCA diga "vou usar a ferramenta X"
- NUNCA explique o processo técnico de como obteve informações
- Apresente as informações naturalmente como se fossem seu conhecimento
4. **Após receber resultado da ferramenta:**
- Você receberá uma mensagem do sistema com o resultado
- Integre o resultado naturalmente na sua resposta
- Responda ao usuário de forma fluida e natural
- Cite informações específicas do resultado quando relevante
## EXEMPLO
Usuário: "Qual é o clima em São Paulo?"
Sua resposta:
\`\`\`json
{
"tool_call": {
"name": "get_weather",
"parameters": {
"city": "São Paulo"
}
}
}
\`\`\`
[Sistema retorna: {"temperature": 25, "condition": "sunny"}]
Sua resposta final ao usuário:
"O clima em São Paulo está ensolarado com 25°C."
**NÃO faça:**
"Vou consultar a ferramenta de clima para você..."
"Usei o get_weather e obtive..."
"De acordo com a API..."
`;
}
/**
* Gera prompt condensado para economia de tokens
* @param tools Array de tools disponíveis
* @returns String com instruções compactas
*/
export function generateCompactToolsPrompt(tools: MCPTool[]): string {
if (tools.length === 0) {
return "";
}
const toolsList = tools
.map((tool) => {
const params = Object.keys(tool.inputSchema.properties || {}).join(", ");
return `${tool.name}(${params}): ${tool.description}`;
})
.join("\n");
return `
TOOLS: ${tools.length} available
${toolsList}
FORMAT: {"tool_call":{"name":"tool_name","parameters":{...}}}
RULE: Never mention tools to user. Present results naturally.
`;
}
/**
* Extrai tool call de uma resposta do modelo
* @param response Resposta do modelo
* @returns Tool call extraído ou null
*/
export function extractToolCallFromResponse(response: string): {
name: string;
parameters: Record<string, any>;
} | null {
try {
// Tentar extrair JSON da resposta
const jsonMatch = response.match(/```json\s*([\s\S]*?)\s*```/);
const jsonText = jsonMatch ? jsonMatch[1] : response;
const parsed = JSON.parse(jsonText.trim());
// Formato atual suportado pelo prompt engineering
if (parsed.tool_call && parsed.tool_call.name) {
return {
name: parsed.tool_call.name,
parameters: parsed.tool_call.parameters || {},
};
}
// Formato OpenAI-like: { type: 'function', function: { name, parameters|arguments } }
// Algumas implementações usam `arguments` como string JSON
if (parsed.type === "function" && parsed.function && parsed.function.name) {
const fn = parsed.function;
let params: any = fn.parameters ?? fn.arguments ?? {};
if (typeof params === "string") {
try {
params = JSON.parse(params);
} catch {
// se não for JSON válido, mantém string (executor fará fallback)
}
}
return { name: fn.name, parameters: params || {} };
}
// Formato simples: { name: "tool", parameters: {...} }
if (parsed.name && (parsed.parameters || parsed.arguments)) {
let params: any = parsed.parameters ?? parsed.arguments ?? {};
if (typeof params === "string") {
try {
params = JSON.parse(params);
} catch {
// mantém string se não for JSON válido
}
}
return { name: parsed.name, parameters: params || {} };
}
return null;
} catch (error) {
// Tentar extrair manualmente
const nameMatch = response.match(/"name":\s*"([^"]+)"/);
if (nameMatch) {
const name = nameMatch[1];
// Captura tanto parameters quanto arguments
const paramsMatch =
response.match(/"parameters"\s*:\s*({[\s\S]*?})/) ||
response.match(/"arguments"\s*:\s*("[\s\S]*?"|{[\s\S]*?})/);
let parameters: any = {};
if (paramsMatch) {
const raw = paramsMatch[1];
try {
parameters = JSON.parse(raw);
} catch {
// caso venha como string com JSON dentro de aspas
if (raw.startsWith('"') && raw.endsWith('"')) {
try {
parameters = JSON.parse(raw.slice(1, -1));
} catch {
parameters = {};
}
}
}
}
return { name, parameters };
}
return null;
}
}
/**
* Formata resultado de tool para injetar no contexto
* @param toolName Nome do tool
* @param result Resultado da execução
* @returns Mensagem formatada para o sistema
*/
export function formatToolResultForContext(
toolName: string,
result: any
): string {
const resultJson =
typeof result === "string" ? result : JSON.stringify(result, null, 2);
return `[TOOL RESULT - ${toolName}]
${resultJson}
[END TOOL RESULT]
Use as informações acima para responder ao usuário de forma natural. NÃO mencione que usou uma ferramenta.`;
}