@hashgraphonline/conversational-agent
Version:
Hashgraph Online conversational AI agent implementing HCS-10 communication, HCS-2 registries, and content inscription on Hedera
137 lines (126 loc) • 4.27 kB
JavaScript
import { StructuredTool } from "@langchain/core/tools";
import { z } from "zod";
import { ChatOpenAI } from "@langchain/openai";
const ResolveEntitiesSchema = z.object({
message: z.string().describe("The message containing entity references to resolve"),
entities: z.array(z.object({
entityId: z.string(),
entityName: z.string(),
entityType: z.string()
})).describe("Available entities in memory")
});
const ExtractEntitiesSchema = z.object({
response: z.string().describe("Agent response text to extract entities from"),
userMessage: z.string().describe("Original user message for context")
});
class ResolveEntitiesTool extends StructuredTool {
constructor(apiKey, modelName = "gpt-4o-mini") {
super();
this.name = "resolve_entities";
this.description = 'Resolves entity references like "the topic", "it", "that" to actual entity IDs';
this.schema = ResolveEntitiesSchema;
this.llm = new ChatOpenAI({
apiKey,
modelName,
temperature: 0
});
}
async _call(input) {
const { message, entities } = input;
if (!entities || entities.length === 0) {
return message;
}
const byType = this.groupEntitiesByType(entities);
const context = this.buildEntityContext(byType);
const prompt = `Task: Replace entity references with IDs.
${context}
Message: "${message}"
Rules:
- "the topic" or "that topic" → replace with most recent topic ID
- "the token" or "that token" → replace with most recent token ID
- "it" or "that" after action verb → replace with most recent entity ID
- "airdrop X" without token ID → add most recent token ID as first parameter
- Token operations without explicit token → use most recent token ID
Examples:
- "submit on the topic" → "submit on 0.0.6543472"
- "airdrop the token" → "airdrop 0.0.123456"
- "airdrop 10 to 0.0.5842697" → "airdrop 0.0.123456 10 to 0.0.5842697"
- "mint 100" → "mint 0.0.123456 100"
Return ONLY the resolved message:`;
try {
const response = await this.llm.invoke(prompt);
return response.content.trim();
} catch (error) {
console.error("[ResolveEntitiesTool] Failed:", error);
return message;
}
}
groupEntitiesByType(entities) {
return entities.reduce((acc, entity) => {
if (!acc[entity.entityType]) {
acc[entity.entityType] = [];
}
acc[entity.entityType].push(entity);
return acc;
}, {});
}
buildEntityContext(groupedEntities) {
let context = "Available entities:\n";
for (const [type, list] of Object.entries(groupedEntities)) {
const recent = list[0];
context += `- Most recent ${type}: "${recent.entityName}" = ${recent.entityId}
`;
}
return context;
}
}
class ExtractEntitiesTool extends StructuredTool {
constructor(apiKey, modelName = "gpt-4o-mini") {
super();
this.name = "extract_entities";
this.description = "Extracts newly created entities from agent responses";
this.schema = ExtractEntitiesSchema;
this.llm = new ChatOpenAI({
apiKey,
modelName,
temperature: 0
});
}
async _call(input) {
const { response, userMessage } = input;
const prompt = `Extract ONLY newly created entities from this response.
User asked: "${userMessage.substring(0, 200)}"
Response: ${response.substring(0, 3e3)}
Look for:
- Success messages with new entity IDs
- Words like "created", "new", "successfully" followed by entity IDs
Return JSON array of created entities:
[{"id": "0.0.XXX", "name": "name", "type": "topic|token|account"}]
If none created, return: []
JSON:`;
try {
const llmResponse = await this.llm.invoke(prompt);
const content = llmResponse.content;
const match = content.match(/\[[\s\S]*?\]/);
if (match) {
return match[0];
}
return "[]";
} catch (error) {
console.error("[ExtractEntitiesTool] Failed:", error);
return "[]";
}
}
}
function createEntityTools(apiKey, modelName = "gpt-4o-mini") {
return {
resolveEntities: new ResolveEntitiesTool(apiKey, modelName),
extractEntities: new ExtractEntitiesTool(apiKey, modelName)
};
}
export {
ExtractEntitiesTool,
ResolveEntitiesTool,
createEntityTools
};
//# sourceMappingURL=index16.js.map