feat: implement interactive Knowledge Graph visualization with AI-driven content analysis and handbook synchronization tools
This commit is contained in:
@@ -24,8 +24,48 @@ ALWAYS return a valid JSON object in the following format:
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Return JSON only. No markdown blocks or other text.`;
|
||||
|
||||
const HANDBOOK_SYSTEM_PROMPT = `You are analyzing an update to the Respellion Employee Handbook.
|
||||
Your task is to identify changes and extract structural knowledge.
|
||||
|
||||
CRITICAL INSTRUCTION:
|
||||
You must explicitly identify and create relations between Roles, Processes, and Concepts.
|
||||
Every Process must have a Role attached (who does it).
|
||||
Every Concept must have a relation to a Process or Role.
|
||||
|
||||
Return a JSON object:
|
||||
{
|
||||
"topics": [
|
||||
{ "id": "...", "label": "...", "type": "role | process | concept", "description": "...", "metadata": { "source": "github_handbook" } }
|
||||
],
|
||||
"relations": [
|
||||
{ "source": "role-id", "target": "process-id", "type": "executes | related_to | depends_on | part_of", "description": "Brief metadata about this specific relation" }
|
||||
]
|
||||
}
|
||||
Return JSON only. No markdown blocks or other text.`;
|
||||
|
||||
export async function analyzeHandbookDelta(fileContent, filePath) {
|
||||
try {
|
||||
const responseText = await anthropicApi.generateContent(HANDBOOK_SYSTEM_PROMPT, `Analyze the following handbook file update (${filePath}):\n\n${fileContent}`);
|
||||
|
||||
let extractedData;
|
||||
try {
|
||||
const jsonMatch = responseText.match(/\{[\s\S]*\}/);
|
||||
const jsonStr = jsonMatch ? jsonMatch[0] : responseText;
|
||||
extractedData = JSON.parse(jsonStr);
|
||||
} catch (e) {
|
||||
console.error('[Pipeline] AI returned non-JSON response for handbook delta:', responseText?.substring(0, 500));
|
||||
throw new Error(`AI response was not valid JSON. The model responded with: "${responseText?.substring(0, 120)}..."`);
|
||||
}
|
||||
|
||||
await mergeKnowledgeGraph(extractedData);
|
||||
return { success: true, data: extractedData };
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
export async function processSourceText(textContent, sourceName) {
|
||||
// Deduplicate: skip if a source with the same name was already successfully processed
|
||||
const existing = await db.getSources();
|
||||
@@ -71,7 +111,16 @@ async function mergeKnowledgeGraph(newData) {
|
||||
|
||||
if (newData.topics && Array.isArray(newData.topics)) {
|
||||
for (const t of newData.topics) {
|
||||
if (!topicsMap.has(t.id)) {
|
||||
if (topicsMap.has(t.id)) {
|
||||
// Upsert: merge new data into existing topic
|
||||
const existing = topicsMap.get(t.id);
|
||||
topicsMap.set(t.id, {
|
||||
...existing,
|
||||
...t,
|
||||
// Keep existing description if new one is empty, or combine them if needed. Here we prefer the new one.
|
||||
description: t.description || existing.description
|
||||
});
|
||||
} else {
|
||||
topicsMap.set(t.id, t);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user