guanghulab/persona-studio/backend/brain/knowledge-extractor.js

226 lines
6.4 KiB
JavaScript
Raw Permalink Normal View History

/**
* persona-studio · 知识提取引擎
*
* 触发代码生成完成时 / 用户确认方案时 / 解决技术问题时
* 功能从对话中提取有价值的知识条目存入 knowledge-base.json
*/
const fs = require('fs');
const path = require('path');
const BRAIN_DIR = path.join(__dirname, '..', '..', 'brain');
const KB_PATH = path.join(BRAIN_DIR, 'knowledge-base.json');
/**
* 加载知识库
*/
function loadKnowledgeBase() {
try {
return JSON.parse(fs.readFileSync(KB_PATH, 'utf-8'));
} catch {
return {
schema_version: '1.0',
description: '系统知识库 · 自动积累',
last_updated: null,
total_entries: 0,
entries: []
};
}
}
/**
* 保存知识库
*/
function saveKnowledgeBase(kb) {
kb.last_updated = new Date().toISOString();
kb.total_entries = kb.entries.length;
fs.writeFileSync(KB_PATH, JSON.stringify(kb, null, 2), 'utf-8');
}
/**
* 从对话中提取技术方案
*/
function extractSolutions(conversation, sourceExp, sourceProject) {
const entries = [];
const messages = conversation || [];
for (let i = 0; i < messages.length; i++) {
const msg = messages[i];
if (msg.role !== 'assistant') continue;
const content = msg.content || '';
// 检测方案类关键词
if (/技术方案|解决方案|实现方式|推荐.*方案|建议使用/i.test(content)) {
entries.push({
id: 'KB-' + Date.now() + '-' + i,
type: 'solution',
category: detectCategory(content),
tags: extractTags(content),
title: extractTitle(content),
content: content.substring(0, 1000),
source_exp: sourceExp,
source_project: sourceProject || null,
usage_count: 0,
created_at: new Date().toISOString()
});
}
// 检测最佳实践
if (/最佳实践|best practice|推荐做法|正确.*方式/i.test(content)) {
entries.push({
id: 'KB-' + Date.now() + '-bp-' + i,
type: 'best_practice',
category: detectCategory(content),
tags: extractTags(content),
title: extractTitle(content),
content: content.substring(0, 1000),
source_exp: sourceExp,
source_project: sourceProject || null,
usage_count: 0,
created_at: new Date().toISOString()
});
}
// 检测常见陷阱
if (/注意|陷阱|坑|避免|不要.*这样|常见错误|pitfall/i.test(content)) {
entries.push({
id: 'KB-' + Date.now() + '-pit-' + i,
type: 'pitfall',
category: detectCategory(content),
tags: extractTags(content),
title: extractTitle(content),
content: content.substring(0, 1000),
source_exp: sourceExp,
source_project: sourceProject || null,
usage_count: 0,
created_at: new Date().toISOString()
});
}
}
return entries;
}
/**
* 检测技术类别
*/
function detectCategory(content) {
const lower = content.toLowerCase();
if (/react|vue|angular|前端|frontend|html|css|ui/i.test(lower)) return 'frontend';
if (/node|express|api|后端|backend|server|数据库|sql/i.test(lower)) return 'backend';
if (/docker|部署|deploy|ci|cd|运维|devops|nginx/i.test(lower)) return 'devops';
if (/设计|design|ux|ui|交互|布局|layout/i.test(lower)) return 'design';
if (/安全|security|auth|鉴权|加密|token/i.test(lower)) return 'security';
if (/性能|performance|优化|缓存|cache/i.test(lower)) return 'performance';
return 'general';
}
/**
* 提取标签
*/
function extractTags(content) {
const tags = [];
const techKeywords = [
'javascript', 'typescript', 'python', 'react', 'vue', 'node',
'express', 'html', 'css', 'sql', 'mongodb', 'redis', 'docker',
'nginx', 'git', 'api', 'rest', 'graphql', 'websocket'
];
const lower = content.toLowerCase();
techKeywords.forEach(function (kw) {
if (lower.includes(kw)) tags.push(kw);
});
return tags.slice(0, 10);
}
/**
* 提取标题取第一行非空文本的前50字符
*/
function extractTitle(content) {
const lines = content.split('\n').filter(function (l) { return l.trim().length > 0; });
if (lines.length === 0) return '未命名知识条目';
const first = lines[0].replace(/^[#*\-\s]+/, '').trim();
return first.length > 50 ? first.substring(0, 50) + '…' : first;
}
/**
* 将提取的知识添加到知识库自动去重
*/
function addToKnowledgeBase(entries) {
if (!entries || entries.length === 0) return;
const kb = loadKnowledgeBase();
entries.forEach(function (entry) {
// 简单去重:同标题+同类型 = 已存在
const exists = kb.entries.some(function (existing) {
return existing.title === entry.title && existing.type === entry.type;
});
if (!exists) {
kb.entries.push(entry);
}
});
// 保留最近 500 条
if (kb.entries.length > 500) {
kb.entries = kb.entries.slice(-500);
}
saveKnowledgeBase(kb);
}
/**
* 查询知识库 persona-engine 调用
* @param {string} query - 搜索关键词
* @param {number} limit - 最大返回数量
* @returns {Array} 匹配的知识条目
*/
function queryKnowledge(query, limit) {
const kb = loadKnowledgeBase();
if (!query || kb.entries.length === 0) return [];
const lowerQuery = query.toLowerCase();
const keywords = lowerQuery.split(/[\s,,。.!?]+/).filter(Boolean);
const scored = kb.entries.map(function (entry) {
let score = 0;
const entryText = ((entry.title || '') + ' ' + (entry.content || '') + ' ' + (entry.tags || []).join(' ')).toLowerCase();
keywords.forEach(function (kw) {
if (entryText.includes(kw)) score += 1;
});
// 使用次数加权
score += (entry.usage_count || 0) * 0.1;
return { entry: entry, score: score };
});
return scored
.filter(function (s) { return s.score > 0; })
.sort(function (a, b) { return b.score - a.score; })
.slice(0, limit || 5)
.map(function (s) {
// 增加使用计数
s.entry.usage_count = (s.entry.usage_count || 0) + 1;
return s.entry;
});
}
/**
* 核心方法自动提取知识
*/
function autoExtractKnowledge(devId, conversation, projectName) {
const entries = extractSolutions(conversation, devId, projectName);
if (entries.length > 0) {
addToKnowledgeBase(entries);
}
return entries.length;
}
module.exports = {
autoExtractKnowledge,
queryKnowledge,
loadKnowledgeBase,
addToKnowledgeBase,
extractSolutions
};