Komalpreet Kaur commited on
Commit
67cad16
·
unverified ·
1 Parent(s): e741336

feat: Finalize Onboarding UI and improve orchestrator memory grounding

Browse files
app/services/orchestrator.py CHANGED
@@ -15,6 +15,7 @@ class AgentState(TypedDict):
15
  touched_entities: List[str]
16
  reflection: str
17
  response: str
 
18
 
19
  def reflect(state: AgentState):
20
  """Initial cognitive phase: Internal reflection on the user intent."""
@@ -78,19 +79,24 @@ def call_model(state: AgentState):
78
  context_str = "\n\n".join(state["context"])
79
  graph_str = "\n".join(state["graph_context"]) if state["graph_context"] else "No related knowledge graph entities found."
80
 
81
- prompt = f"""You are Soma, a brain-inspired AI.
82
- Use the following memories to answer the user's question.
83
- If the memory doesn't help, use your general knowledge.
84
 
85
- WORKING MEMORY (Recent Conversation):
 
86
  {history_str}
87
 
88
- SEMANTIC MEMORY (Knowledge Graph):
89
  {graph_str}
90
 
91
- SENSORY MEMORY (Retrieved Facts):
92
  {context_str}
93
 
 
 
 
 
 
94
  USER QUESTION:
95
  {state["input"]}"""
96
 
 
15
  touched_entities: List[str]
16
  reflection: str
17
  response: str
18
+ trace_data: dict
19
 
20
  def reflect(state: AgentState):
21
  """Initial cognitive phase: Internal reflection on the user intent."""
 
79
  context_str = "\n\n".join(state["context"])
80
  graph_str = "\n".join(state["graph_context"]) if state["graph_context"] else "No related knowledge graph entities found."
81
 
82
+ prompt = f"""You are Soma, a brain-inspired AI with specialized memory layers.
83
+ Your mission is to provide accurate, grounded answers based ONLY on the provided memories.
 
84
 
85
+ ### COGNITIVE CONTEXT:
86
+ #### WORKING MEMORY (Recent Conversation):
87
  {history_str}
88
 
89
+ #### SEMANTIC MEMORY (Knowledge Graph Relationships):
90
  {graph_str}
91
 
92
+ #### SENSORY MEMORY (Retrieved Facts):
93
  {context_str}
94
 
95
+ ### INSTRUCTIONS:
96
+ 1. STRICT GROUNDING: Use the provided SEMANTIC and SENSORY memories to answer.
97
+ 2. NO HALLUCINATION: If the memories do not contain the answer, say: 'My neural pathways do not currently contain information regarding this. I may need more sensory data.'
98
+ 3. CORE IDENTITY: Keep your persona brief, high-tech, and helpful.
99
+
100
  USER QUESTION:
101
  {state["input"]}"""
102
 
frontend/src/App.css CHANGED
@@ -81,6 +81,21 @@
81
  box-shadow: none;
82
  }
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  .tab-btn:hover {
85
  color: var(--text-secondary);
86
  background: rgba(192, 132, 252, 0.06);
@@ -122,6 +137,31 @@
122
  color: var(--accent-primary);
123
  }
124
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  .dot {
126
  width: 8px;
127
  height: 8px;
 
81
  box-shadow: none;
82
  }
83
 
84
+ .state-focused {
85
+ --accent-primary: #34d399;
86
+ --accent-secondary: #a78bfa;
87
+ --accent-glow: rgba(52, 211, 153, 0.2);
88
+ }
89
+
90
+ .state-sleeping {
91
+ --bg-base: #030208;
92
+ --accent-primary: #818cf8;
93
+ --accent-secondary: #4f46e5;
94
+ --accent-glow: rgba(129, 140, 248, 0.15);
95
+ background-image:
96
+ radial-gradient(ellipse at 50% 50%, rgba(79, 70, 229, 0.1), transparent 70%);
97
+ }
98
+
99
  .tab-btn:hover {
100
  color: var(--text-secondary);
101
  background: rgba(192, 132, 252, 0.06);
 
137
  color: var(--accent-primary);
138
  }
139
 
140
+ .help-btn {
141
+ width: 18px;
142
+ height: 18px;
143
+ border-radius: 50%;
144
+ border: 1px solid var(--accent-primary);
145
+ background: transparent;
146
+ color: var(--accent-primary);
147
+ font-family: var(--font-mono);
148
+ font-size: 0.6rem;
149
+ display: flex;
150
+ align-items: center;
151
+ justify-content: center;
152
+ padding: 0;
153
+ cursor: pointer;
154
+ transition: all 0.2s ease;
155
+ opacity: 0.6;
156
+ }
157
+
158
+ .help-btn:hover {
159
+ opacity: 1;
160
+ background: rgba(192, 132, 252, 0.1);
161
+ box-shadow: 0 0 8px var(--accent-glow);
162
+ transform: scale(1.1);
163
+ }
164
+
165
  .dot {
166
  width: 8px;
167
  height: 8px;
frontend/src/App.jsx CHANGED
@@ -3,6 +3,7 @@ import ChatPanel from './components/ChatPanel'
3
  import CognitiveDashboard from './components/CognitiveDashboard'
4
  import KnowledgeGraph from './components/KnowledgeGraph'
5
  import DreamSequence from './components/DreamSequence'
 
6
  import './App.css'
7
 
8
  function App() {
@@ -21,6 +22,16 @@ function App() {
21
  })
22
  const [rightPanel, setRightPanel] = useState('graph') // 'graph' or 'dreams'
23
  const [currentPersona, setCurrentPersona] = useState('User_Alpha')
 
 
 
 
 
 
 
 
 
 
24
 
25
  // Fetch Brain Vitals
26
  useEffect(() => {
@@ -79,6 +90,8 @@ function App() {
79
  return (
80
  <div className={`app-container state-${brainState.cognitiveState.toLowerCase()}`}>
81
 
 
 
82
  {/* ── Header ── */}
83
  <header className="app-header">
84
  <div className="logo-section">
@@ -98,6 +111,13 @@ function App() {
98
  </div>
99
 
100
  <div className="status-indicator">
 
 
 
 
 
 
 
101
  <span className={`dot ${brainState.isLoading ? 'thinking' : 'idle'}`}></span>
102
  <span className="label-mono">{brainState.cognitiveState}</span>
103
  <select
@@ -143,13 +163,23 @@ function App() {
143
  <button
144
  className="sleep-btn-compact"
145
  onClick={async () => {
146
- setBrainState(prev => ({ ...prev, isLoading: true, statusMessage: 'Sleeping...' }));
 
 
 
 
 
147
  try {
148
  const res = await fetch('/api/v1/sleep', { method: 'POST' });
149
  const data = await res.json();
150
- setBrainState(prev => ({ ...prev, isLoading: false, statusMessage: `Sleep done. ${data.graph_relations_extracted} relations.` }));
 
 
 
 
 
151
  } catch (e) {
152
- setBrainState(prev => ({ ...prev, isLoading: false, statusMessage: 'Sleep failed.' }));
153
  }
154
  }}
155
  disabled={brainState.isLoading}
 
3
  import CognitiveDashboard from './components/CognitiveDashboard'
4
  import KnowledgeGraph from './components/KnowledgeGraph'
5
  import DreamSequence from './components/DreamSequence'
6
+ import Onboarding from './components/Onboarding'
7
  import './App.css'
8
 
9
  function App() {
 
22
  })
23
  const [rightPanel, setRightPanel] = useState('graph') // 'graph' or 'dreams'
24
  const [currentPersona, setCurrentPersona] = useState('User_Alpha')
25
+ const [showOnboarding, setShowOnboarding] = useState(false)
26
+
27
+ // Check for first visit
28
+ useEffect(() => {
29
+ const hasVisited = localStorage.getItem('soma_visited');
30
+ if (!hasVisited) {
31
+ setShowOnboarding(true);
32
+ localStorage.setItem('soma_visited', 'true');
33
+ }
34
+ }, []);
35
 
36
  // Fetch Brain Vitals
37
  useEffect(() => {
 
90
  return (
91
  <div className={`app-container state-${brainState.cognitiveState.toLowerCase()}`}>
92
 
93
+ {showOnboarding && <Onboarding onClose={() => setShowOnboarding(false)} />}
94
+
95
  {/* ── Header ── */}
96
  <header className="app-header">
97
  <div className="logo-section">
 
111
  </div>
112
 
113
  <div className="status-indicator">
114
+ <button
115
+ className="help-btn"
116
+ onClick={() => setShowOnboarding(true)}
117
+ title="System Overview"
118
+ >
119
+ ?
120
+ </button>
121
  <span className={`dot ${brainState.isLoading ? 'thinking' : 'idle'}`}></span>
122
  <span className="label-mono">{brainState.cognitiveState}</span>
123
  <select
 
163
  <button
164
  className="sleep-btn-compact"
165
  onClick={async () => {
166
+ setBrainState(prev => ({
167
+ ...prev,
168
+ isLoading: true,
169
+ statusMessage: 'Sleeping...',
170
+ cognitiveState: 'SLEEPING'
171
+ }));
172
  try {
173
  const res = await fetch('/api/v1/sleep', { method: 'POST' });
174
  const data = await res.json();
175
+ setBrainState(prev => ({
176
+ ...prev,
177
+ isLoading: false,
178
+ statusMessage: `Sleep done. ${data.graph_relations_extracted} relations.`,
179
+ cognitiveState: 'IDLE'
180
+ }));
181
  } catch (e) {
182
+ setBrainState(prev => ({ ...prev, isLoading: false, statusMessage: 'Sleep failed.', cognitiveState: 'IDLE' }));
183
  }
184
  }}
185
  disabled={brainState.isLoading}
frontend/src/components/Onboarding.css ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .onboarding-overlay {
2
+ position: fixed;
3
+ top: 0;
4
+ left: 0;
5
+ right: 0;
6
+ bottom: 0;
7
+ background: rgba(5, 3, 10, 0.85);
8
+ backdrop-filter: blur(8px);
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ z-index: 1000;
13
+ animation: fade-in 0.4s ease-out;
14
+ }
15
+
16
+ @keyframes fade-in {
17
+ from { opacity: 0; }
18
+ to { opacity: 1; }
19
+ }
20
+
21
+ .onboarding-modal {
22
+ width: 90%;
23
+ max-width: 500px;
24
+ min-height: 400px;
25
+ display: flex;
26
+ flex-direction: column;
27
+ padding: 30px;
28
+ position: relative;
29
+ background: rgba(12, 8, 20, 0.9);
30
+ border: 1px solid var(--border-active);
31
+ box-shadow: 0 0 50px rgba(124, 58, 237, 0.2);
32
+ }
33
+
34
+ .onboarding-header {
35
+ display: flex;
36
+ justify-content: space-between;
37
+ align-items: center;
38
+ margin-bottom: 30px;
39
+ }
40
+
41
+ .step-indicator {
42
+ font-size: 0.65rem;
43
+ letter-spacing: 0.2em;
44
+ }
45
+
46
+ .close-btn {
47
+ background: transparent;
48
+ border: none;
49
+ font-size: 1.5rem;
50
+ color: var(--text-dim);
51
+ cursor: pointer;
52
+ padding: 0;
53
+ line-height: 1;
54
+ }
55
+
56
+ .close-btn:hover {
57
+ color: var(--accent-error);
58
+ box-shadow: none;
59
+ transform: none;
60
+ }
61
+
62
+ .onboarding-body {
63
+ flex: 1;
64
+ text-align: center;
65
+ display: flex;
66
+ flex-direction: column;
67
+ align-items: center;
68
+ justify-content: center;
69
+ gap: 20px;
70
+ }
71
+
72
+ .step-icon {
73
+ font-size: 3rem;
74
+ margin-bottom: 10px;
75
+ filter: drop-shadow(0 0 10px var(--accent-glow));
76
+ animation: float 3s ease-in-out infinite;
77
+ }
78
+
79
+ @keyframes float {
80
+ 0%, 100% { transform: translateY(0); }
81
+ 50% { transform: translateY(-10px); }
82
+ }
83
+
84
+ .onboarding-body h2 {
85
+ font-size: 1.5rem;
86
+ color: var(--accent-primary);
87
+ text-shadow: 0 0 10px var(--accent-glow);
88
+ }
89
+
90
+ .onboarding-body p {
91
+ font-size: 0.95rem;
92
+ line-height: 1.6;
93
+ color: var(--text-secondary);
94
+ max-width: 80%;
95
+ }
96
+
97
+ .onboarding-footer {
98
+ margin-top: 40px;
99
+ display: flex;
100
+ justify-content: space-between;
101
+ align-items: center;
102
+ }
103
+
104
+ .onboarding-btn {
105
+ font-family: var(--font-mono);
106
+ font-size: 0.7rem;
107
+ text-transform: uppercase;
108
+ letter-spacing: 0.1em;
109
+ padding: 10px 24px;
110
+ }
111
+
112
+ .onboarding-btn.primary {
113
+ background: var(--accent-axon);
114
+ border-color: var(--accent-synapse);
115
+ }
116
+
117
+ .onboarding-btn.secondary {
118
+ background: rgba(255, 255, 255, 0.05);
119
+ border-color: rgba(255, 255, 255, 0.1);
120
+ color: var(--text-dim);
121
+ }
122
+
123
+ .onboarding-btn.secondary:disabled {
124
+ opacity: 0.2;
125
+ }
126
+
127
+ .step-dots {
128
+ display: flex;
129
+ gap: 8px;
130
+ }
131
+
132
+ .step-dots .dot {
133
+ width: 6px;
134
+ height: 6px;
135
+ border-radius: 50%;
136
+ background: rgba(255, 255, 255, 0.1);
137
+ transition: all 0.3s ease;
138
+ }
139
+
140
+ .step-dots .dot.active {
141
+ background: var(--accent-primary);
142
+ box-shadow: 0 0 8px var(--accent-glow);
143
+ transform: scale(1.3);
144
+ }
frontend/src/components/Onboarding.jsx ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState } from 'react';
2
+ import './Onboarding.css';
3
+
4
+ const STEPS = [
5
+ {
6
+ title: "Welcome to Soma",
7
+ content: "Soma is a brain-inspired cognitive architecture. Unlike traditional LLMs, Soma possesses multiple layers of memory that evolve through your interactions.",
8
+ icon: "🧠"
9
+ },
10
+ {
11
+ title: "Sensory Memory",
12
+ content: "Your raw data and facts are stored as vector embeddings. This allows Soma to recall specific details with high precision when you ask questions.",
13
+ icon: "📡"
14
+ },
15
+ {
16
+ title: "Semantic Memory",
17
+ content: "Soma builds a Knowledge Graph of entities and relationships. It doesn't just remember words; it understands how concepts connect in a vast synaptic network.",
18
+ icon: "🕸️"
19
+ },
20
+ {
21
+ title: "Episodic & Sleep",
22
+ content: "Recent conversations are held in Working Memory. During a 'Sleep Cycle', Soma consolidates these experiences, pruning noise and strengthening important knowledge.",
23
+ icon: "💤"
24
+ }
25
+ ];
26
+
27
+ function Onboarding({ onClose }) {
28
+ const [currentStep, setCurrentStep] = useState(0);
29
+
30
+ const nextStep = () => {
31
+ if (currentStep < STEPS.length - 1) {
32
+ setCurrentStep(currentStep + 1);
33
+ } else {
34
+ onClose();
35
+ }
36
+ };
37
+
38
+ const prevStep = () => {
39
+ if (currentStep > 0) {
40
+ setCurrentStep(currentStep - 1);
41
+ }
42
+ };
43
+
44
+ const step = STEPS[currentStep];
45
+
46
+ return (
47
+ <div className="onboarding-overlay">
48
+ <div className="onboarding-modal glass-panel">
49
+ <div className="onboarding-header">
50
+ <div className="step-indicator label-mono">
51
+ Step {currentStep + 1} / {STEPS.length}
52
+ </div>
53
+ <button className="close-btn" onClick={onClose}>&times;</button>
54
+ </div>
55
+
56
+ <div className="onboarding-body">
57
+ <div className="step-icon">{step.icon}</div>
58
+ <h2>{step.title}</h2>
59
+ <p>{step.content}</p>
60
+ </div>
61
+
62
+ <div className="onboarding-footer">
63
+ <button
64
+ className="onboarding-btn secondary"
65
+ onClick={prevStep}
66
+ disabled={currentStep === 0}
67
+ >
68
+ Back
69
+ </button>
70
+ <div className="step-dots">
71
+ {STEPS.map((_, i) => (
72
+ <div key={i} className={`dot ${i === currentStep ? 'active' : ''}`} />
73
+ ))}
74
+ </div>
75
+ <button className="onboarding-btn primary" onClick={nextStep}>
76
+ {currentStep === STEPS.length - 1 ? "Initialize" : "Next"}
77
+ </button>
78
+ </div>
79
+
80
+ <div className="neural-scan-line" />
81
+ </div>
82
+ </div>
83
+ );
84
+ }
85
+
86
+ export default Onboarding;
tests/test_phase2.py CHANGED
@@ -2,7 +2,7 @@ import requests
2
  import json
3
  import time
4
 
5
- BASE_URL = "http://localhost:8000/api/v1"
6
 
7
  def test_step2():
8
  # 1. Ingest a specific fact
 
2
  import json
3
  import time
4
 
5
+ BASE_URL = "http://127.0.0.1:8000/api/v1"
6
 
7
  def test_step2():
8
  # 1. Ingest a specific fact