code clean up pass
This commit is contained in:
@@ -39,7 +39,6 @@ export default function App() {
|
|||||||
const [viewHistory, setViewHistory] = useState([]);
|
const [viewHistory, setViewHistory] = useState([]);
|
||||||
const [activeProject, setActiveProject] = useState(null);
|
const [activeProject, setActiveProject] = useState(null);
|
||||||
const { projects, refreshProjects } = useProjects();
|
const { projects, refreshProjects } = useProjects();
|
||||||
const [summarising, setSummarising] = useState(false);
|
|
||||||
|
|
||||||
// Lifted model props — available to header + SettingsView
|
// Lifted model props — available to header + SettingsView
|
||||||
const [modelProps, setModelProps] = useState(null);
|
const [modelProps, setModelProps] = useState(null);
|
||||||
@@ -66,6 +65,7 @@ export default function App() {
|
|||||||
streaming,
|
streaming,
|
||||||
lastTokenCount,
|
lastTokenCount,
|
||||||
lastModel,
|
lastModel,
|
||||||
|
useChat,
|
||||||
} = useChat({ activeSession, appendMessage, updateLastMessage, refreshSessions });
|
} = useChat({ activeSession, appendMessage, updateLastMessage, refreshSessions });
|
||||||
|
|
||||||
function navigate(nextView) {
|
function navigate(nextView) {
|
||||||
|
|||||||
@@ -108,5 +108,6 @@ export function useChat({ activeSession, appendMessage, updateLastMessage, refre
|
|||||||
error,
|
error,
|
||||||
lastTokenCount,
|
lastTokenCount,
|
||||||
lastModel,
|
lastModel,
|
||||||
|
summarising,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
const semantic = require('../semantic')
|
const semantic = require('../semantic')
|
||||||
const { getEnv, SERVICES, formatEpisodeText } = require('@nexusai/shared');
|
const { getEnv, SERVICES, formatEpisodeText, ENTITIES } = require('@nexusai/shared');
|
||||||
const { upsertEntity } = require('./index');
|
const { upsertEntity } = require('./index');
|
||||||
|
|
||||||
const EXTRACTION_URL = getEnv('EXTRACTION_URL', 'http://localhost:11434');
|
const EXTRACTION_URL = getEnv('EXTRACTION_URL', 'http://localhost:11434');
|
||||||
@@ -63,12 +63,8 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null)
|
|||||||
try {
|
try {
|
||||||
// Fetch existing entities to guide the model toward consistent name/type pairs
|
// Fetch existing entities to guide the model toward consistent name/type pairs
|
||||||
const db = require('../db').getDB();
|
const db = require('../db').getDB();
|
||||||
console.log('[entities] fetching known entities...'); // add this
|
|
||||||
const knownEntities = db.prepare(`SELECT name, type FROM entities ORDER BY rowid DESC LIMIT 20`).all();
|
const knownEntities = db.prepare(`SELECT name, type FROM entities ORDER BY rowid DESC LIMIT 20`).all();
|
||||||
console.log('[entities] known entities count:', knownEntities.length);
|
|
||||||
|
|
||||||
const prompt = buildExtractionPrompt(userMessage, aiResponse, knownEntities);
|
const prompt = buildExtractionPrompt(userMessage, aiResponse, knownEntities);
|
||||||
console.log('[entities] prompt preview:', JSON.stringify(prompt.slice(-300)));
|
|
||||||
|
|
||||||
|
|
||||||
const res = await fetch(`${EXTRACTION_URL}/api/generate`, {
|
const res = await fetch(`${EXTRACTION_URL}/api/generate`, {
|
||||||
@@ -80,8 +76,8 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null)
|
|||||||
stream: false,
|
stream: false,
|
||||||
format: 'json',
|
format: 'json',
|
||||||
options: {
|
options: {
|
||||||
temperature: 0.1,
|
temperature: ENTITIES.TEMPERATURE,
|
||||||
num_predict: 1024,
|
num_predict: ENTITIES.NUM_PREDICT,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -90,7 +86,6 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null)
|
|||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
const raw = data.response?.trim() ?? '';
|
const raw = data.response?.trim() ?? '';
|
||||||
console.log('[entities] raw response:', JSON.stringify(raw.slice(0, 300)));
|
|
||||||
|
|
||||||
const parsed = JSON.parse(raw);
|
const parsed = JSON.parse(raw);
|
||||||
const entities = Array.isArray(parsed.entities) ? parsed.entities : [];
|
const entities = Array.isArray(parsed.entities) ? parsed.entities : [];
|
||||||
@@ -122,7 +117,6 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null)
|
|||||||
}))
|
}))
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.warn(`[entities] Failed to embed entity "${entity.name}":`, err.message);
|
console.warn(`[entities] Failed to embed entity "${entity.name}":`, err.message);
|
||||||
console.warn(`[entities] Embed error stack:`, err.stack); // add this
|
|
||||||
});
|
});
|
||||||
|
|
||||||
saved++;
|
saved++;
|
||||||
@@ -133,7 +127,6 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null)
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Non-critical — log and move on, episode is already saved
|
// Non-critical — log and move on, episode is already saved
|
||||||
console.warn('[entities] Extraction failed:', err.message);
|
console.warn('[entities] Extraction failed:', err.message);
|
||||||
console.warn('[entities] Stack:', err.stack);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function getSession(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getSessions(limit = EPISODIC.DEFAULT_PAGE_SIZE, offset = 0, projectId = null) {
|
function getSessions(limit = EPISODIC.DEFAULT_PAGE_SIZE, offset = EPISODIC.DEFAULT_OFFSET, projectId = null) {
|
||||||
const db = getDB();
|
const db = getDB();
|
||||||
const stmt = projectId
|
const stmt = projectId
|
||||||
? db.prepare(`
|
? db.prepare(`
|
||||||
@@ -143,7 +143,7 @@ function getEpisode(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieves episodes for a given session, ordered by creation time descending, with pagination
|
// Retrieves episodes for a given session, ordered by creation time descending, with pagination
|
||||||
function getEpisodesBySession(sessionId, limit = EPISODIC.DEFAULT_PAGE_SIZE, offset = 0) {
|
function getEpisodesBySession(sessionId, limit = EPISODIC.DEFAULT_PAGE_SIZE, offset = EPISODIC.DEFAULT_OFFSET) {
|
||||||
const db = getDB();
|
const db = getDB();
|
||||||
const stmt = db.prepare(`
|
const stmt = db.prepare(`
|
||||||
SELECT * FROM episodes
|
SELECT * FROM episodes
|
||||||
|
|||||||
@@ -317,10 +317,7 @@ async function chatStream(externalId, userMessage, onChunk, options = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("[orchestration] final streamed text length:", fullText.length);
|
|
||||||
|
|
||||||
if (fullText.trim()) {
|
if (fullText.trim()) {
|
||||||
console.log('[chat] tokenCount before save:', tokenCount);
|
|
||||||
await memory.createEpisode(session.id, userMessage, fullText, tokenCount, session.project_id ?? null);
|
await memory.createEpisode(session.id, userMessage, fullText, tokenCount, session.project_id ?? null);
|
||||||
const allEpisodes = await memory.getRecentEpisodes(session.id, 9999);
|
const allEpisodes = await memory.getRecentEpisodes(session.id, 9999);
|
||||||
triggerSummary(session, allEpisodes);
|
triggerSummary(session, allEpisodes);
|
||||||
|
|||||||
@@ -77,12 +77,9 @@ async function maybeSummarize(session, allEpisodes) {
|
|||||||
// 1. Sum total tokens for this session
|
// 1. Sum total tokens for this session
|
||||||
const totalTokens = allEpisodes.reduce((sum, ep) => sum + (ep.token_count || 0), 0);
|
const totalTokens = allEpisodes.reduce((sum, ep) => sum + (ep.token_count || 0), 0);
|
||||||
if (totalTokens < THRESHOLD_TOKENS) return; // under threshold — nothing to do
|
if (totalTokens < THRESHOLD_TOKENS) return; // under threshold — nothing to do
|
||||||
console.log('[summarization] fetching existing summaries...');
|
|
||||||
// 2. Fetch existing summaries for session
|
// 2. Fetch existing summaries for session
|
||||||
const summariesRes = await fetch(`${MEMORY_URL}/sessions/${session.id}/summaries`);
|
const summariesRes = await fetch(`${MEMORY_URL}/sessions/${session.id}/summaries`);
|
||||||
console.log('[summarization] memory URL:', MEMORY_URL);
|
|
||||||
console.log('[summarization] session:', session.id, session.external_id);
|
|
||||||
console.log('[summarization] summaries fetch status:', summariesRes.status);
|
|
||||||
if (!summariesRes.ok) return;
|
if (!summariesRes.ok) return;
|
||||||
const summaries = await summariesRes.json();
|
const summaries = await summariesRes.json();
|
||||||
|
|
||||||
@@ -96,19 +93,18 @@ async function maybeSummarize(session, allEpisodes) {
|
|||||||
if (newEpisodes.length < MIN_EPISODES_SINCE) return;
|
if (newEpisodes.length < MIN_EPISODES_SINCE) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Determine episode range string e.g. "1-42"
|
// 4. Determine episodes to summarize
|
||||||
const ids = allEpisodes.map(ep => ep.id).sort((a,b) => a - b);
|
const episodesToSummarize = latest
|
||||||
const episodeRange = `${ids.at(0)}-${ids.at(-1)}`;
|
? allEpisodes.filter(ep => ep.id > lastCoveredId)
|
||||||
const totalEpisodeTokens = allEpisodes.reduce((sum, ep) => sum + (ep.token_count || 0), 0);
|
: allEpisodes;
|
||||||
|
|
||||||
// 5. Generate summary — pass existing content if updating
|
// 5. Determine episode range from the episodes actually being summarized
|
||||||
const episodesToSummarize = latest
|
const summarizedIds = episodesToSummarize.map(ep => ep.id).sort((a,b) => a - b);
|
||||||
? allEpisodes.filter(ep => ep.id > lastCoveredId)
|
const episodeRange = `${summarizedIds.at(0)}-${summarizedIds.at(-1)}`;
|
||||||
: allEpisodes;
|
const totalEpisodeTokens = allEpisodes.reduce((sum, ep) => sum + (ep.token_count || 0), 0);
|
||||||
|
|
||||||
// add temporarily before the generateSummary call
|
// add temporarily before the generateSummary call
|
||||||
console.log('[summarization] episodes to summarize:', episodesToSummarize.length);
|
console.log('[summarization] episodes to summarize:', episodesToSummarize.length);
|
||||||
console.log('[summarization] total chars:', episodesToSummarize.reduce((s, ep) => s + ep.user_message.length + ep.ai_response.length, 0));
|
|
||||||
|
|
||||||
const content = await generateSummary(
|
const content = await generateSummary(
|
||||||
episodesToSummarize,
|
episodesToSummarize,
|
||||||
|
|||||||
@@ -74,6 +74,12 @@ const SUMMARIES = {
|
|||||||
MAX_SUMMARY_TOKENS: 800, //if existing summary exceeds this, create new instead of update
|
MAX_SUMMARY_TOKENS: 800, //if existing summary exceeds this, create new instead of update
|
||||||
MIN_EPISODES_SINCE: 5, // don't resummarize until N new episodes since last summary
|
MIN_EPISODES_SINCE: 5, // don't resummarize until N new episodes since last summary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ENTITIES = {
|
||||||
|
TEMPERATURE: 0.1,
|
||||||
|
NUM_PREDICT: 1024,
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
QDRANT,
|
QDRANT,
|
||||||
COLLECTIONS,
|
COLLECTIONS,
|
||||||
@@ -85,5 +91,6 @@ module.exports = {
|
|||||||
INFERENCE_DEFAULTS,
|
INFERENCE_DEFAULTS,
|
||||||
SQLITE,
|
SQLITE,
|
||||||
ORCHESTRATION,
|
ORCHESTRATION,
|
||||||
SUMMARIES
|
SUMMARIES,
|
||||||
|
ENTITIES
|
||||||
};
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
const {getEnv} = require('./config/env');
|
const {getEnv} = require('./config/env');
|
||||||
const {QDRANT, COLLECTIONS, EPISODIC, SERVICES, OLLAMA, PORTS, LLAMACPP, INFERENCE_DEFAULTS, SQLITE, ORCHESTRATION, SUMMARIES } = require('./config/constants');
|
const {QDRANT, COLLECTIONS, EPISODIC, SERVICES, OLLAMA, PORTS, LLAMACPP, INFERENCE_DEFAULTS, SQLITE, ORCHESTRATION, SUMMARIES, ENTITIES } = require('./config/constants');
|
||||||
const {parseRow, formatEpisodeText} = require('./utils')
|
const {parseRow, formatEpisodeText} = require('./utils')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
@@ -17,4 +17,5 @@ module.exports = {
|
|||||||
parseRow,
|
parseRow,
|
||||||
formatEpisodeText,
|
formatEpisodeText,
|
||||||
SUMMARIES,
|
SUMMARIES,
|
||||||
|
ENTITIES,
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user