MEMORY SYSTEM ARCHITECTURE: - Weaviate-based memory storage (Thought, Message, Conversation collections) - GPU embeddings with BAAI/bge-m3 (1024-dim, RTX 4070) - 9 MCP tools for Claude Desktop integration CORE MODULES (memory/): - core/embedding_service.py: GPU embedder singleton with PyTorch - schemas/memory_schemas.py: Weaviate schema definitions - mcp/thought_tools.py: add_thought, search_thoughts, get_thought - mcp/message_tools.py: add_message, get_messages, search_messages - mcp/conversation_tools.py: get_conversation, search_conversations, list_conversations FLASK TEMPLATES: - conversation_view.html: Display single conversation with messages - conversations.html: List all conversations with search - memories.html: Browse and search thoughts FEATURES: - Semantic search across thoughts, messages, conversations - Privacy levels (private, shared, public) - Thought types (reflection, question, intuition, observation) - Conversation categories with filtering - Message ordering and role-based display DATA (as of 2026-01-08): - 102 Thoughts - 377 Messages - 12 Conversations DOCUMENTATION: - memory/README_MCP_TOOLS.md: Complete API reference and usage examples All MCP tools tested and validated (see test_memory_mcp_tools.py in archive). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
125 lines
4.6 KiB
HTML
125 lines
4.6 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Conversations{% endblock %}
|
|
|
|
{% block content %}
|
|
<section class="section">
|
|
<h1 class="text-center">Conversations Ikario</h1>
|
|
<p class="lead text-center">Liste des conversations David-Ikario</p>
|
|
|
|
<div class="ornament">· · ·</div>
|
|
|
|
<!-- Search Box -->
|
|
<div class="card">
|
|
<h2>🔍 Recherche sémantique</h2>
|
|
<div class="form-row">
|
|
<input
|
|
type="text"
|
|
id="searchQuery"
|
|
class="form-control"
|
|
placeholder="Ex: discussions sur la philosophie..."
|
|
style="flex: 1;"
|
|
>
|
|
<button onclick="searchConversations()" class="btn btn-primary">Rechercher</button>
|
|
</div>
|
|
<div id="searchResults" class="mt-3"></div>
|
|
</div>
|
|
|
|
<hr class="divider">
|
|
|
|
<!-- Conversations List -->
|
|
<div class="card">
|
|
<h2>📚 Toutes les conversations ({{ conversations|length }})</h2>
|
|
|
|
{% if conversations %}
|
|
<div class="results-list mt-2">
|
|
{% for conv in conversations %}
|
|
<div class="result-item">
|
|
<div class="result-header">
|
|
<a href="/conversation/{{ conv.conversation_id }}" style="font-weight: 600;">
|
|
{{ conv.conversation_id }}
|
|
</a>
|
|
<span class="badge">{{ conv.category }}</span>
|
|
<span class="text-muted">{{ conv.message_count }} messages</span>
|
|
</div>
|
|
<div class="result-text">{{ conv.summary }}</div>
|
|
<div class="result-meta">
|
|
<span class="text-muted">
|
|
{{ conv.timestamp_start[:10] if conv.timestamp_start else 'Date inconnue' }}
|
|
</span>
|
|
<span class="text-muted">
|
|
Participants: {{ conv.participants|join(', ') if conv.participants else 'N/A' }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<p class="text-muted mt-2">Aucune conversation trouvée</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="text-center mt-3">
|
|
<a href="/memories" class="btn">Retour aux recherches Memory</a>
|
|
</div>
|
|
</section>
|
|
|
|
<script>
|
|
async function searchConversations() {
|
|
const query = document.getElementById('searchQuery').value;
|
|
const resultsDiv = document.getElementById('searchResults');
|
|
|
|
if (!query.trim()) {
|
|
resultsDiv.innerHTML = '<p class="text-muted">Entrez une requête de recherche</p>';
|
|
return;
|
|
}
|
|
|
|
resultsDiv.innerHTML = '<p class="text-muted">Recherche en cours...</p>';
|
|
|
|
try {
|
|
const response = await fetch('/api/conversations/search', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({query, limit: 10})
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success && data.results && data.results.length > 0) {
|
|
let html = '<div class="results-list">';
|
|
data.results.forEach((conv, idx) => {
|
|
html += `
|
|
<div class="result-item">
|
|
<div class="result-header">
|
|
<a href="/conversation/${conv.conversation_id}" style="font-weight: 600;">
|
|
${conv.conversation_id}
|
|
</a>
|
|
<span class="badge">${conv.category}</span>
|
|
<span class="text-muted">${conv.message_count} messages</span>
|
|
</div>
|
|
<div class="result-text">${conv.summary}</div>
|
|
<div class="result-meta">
|
|
<span class="text-muted">
|
|
${conv.timestamp_start ? conv.timestamp_start.substring(0,10) : 'Date inconnue'}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
`;
|
|
});
|
|
html += '</div>';
|
|
resultsDiv.innerHTML = html;
|
|
} else {
|
|
resultsDiv.innerHTML = '<p class="text-muted">Aucun résultat trouvé</p>';
|
|
}
|
|
} catch (error) {
|
|
resultsDiv.innerHTML = `<p class="text-danger">Erreur: ${error.message}</p>';
|
|
}
|
|
}
|
|
|
|
// Allow Enter key to trigger search
|
|
document.getElementById('searchQuery').addEventListener('keypress', function(e) {
|
|
if (e.key === 'Enter') searchConversations();
|
|
});
|
|
</script>
|
|
{% endblock %}
|