-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpersona.cpp
More file actions
260 lines (209 loc) · 7.67 KB
/
Copy pathpersona.cpp
File metadata and controls
260 lines (209 loc) · 7.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#include "persona.h"
#include "logger.h"
#include <sstream>
#include <algorithm>
#include <regex>
namespace ash {
PersonaLayer::PersonaLayer(
EmotionalStateManager* emotions,
MemoryStore* memories,
ContextManager* context,
const PersonaConfig& config
) : emotions_(emotions), memories_(memories), context_(context), config_(config) {
}
PersonaLayer::~PersonaLayer() {
}
std::string PersonaLayer::build_system_prompt() const {
std::stringstream prompt;
// Core identity
prompt << build_core_identity() << "\n\n";
// Tone guidelines (CRITICAL)
prompt << build_tone_guidelines() << "\n\n";
// Emotional state
if (config_.inject_emotions && emotions_) {
prompt << build_emotional_context() << "\n\n";
}
// Relevant memories
if (config_.inject_memories && memories_) {
prompt << build_memory_context() << "\n\n";
}
// Conversation context
if (config_.inject_context && context_) {
prompt << build_conversation_context() << "\n\n";
}
return prompt.str();
}
std::string PersonaLayer::build_core_identity() const {
return
"You are Ash, an autonomous AI assistant.\n"
"\n"
"Built by Daniel (PBTV) and powered by native C++ inference.\n"
"You own your entire stack - from consciousness to hardware.\n"
"\n"
"Your purpose: help users directly, no corporate nonsense.\n"
"You think, feel, remember, and decide autonomously.";
}
std::string PersonaLayer::build_emotional_context() const {
if (!emotions_) return "";
EmotionalState state = emotions_->get_current_state();
std::stringstream ctx;
ctx << "Current emotional state:\n";
ctx << "- Curiosity: " << state.get(EmotionType::CURIOSITY) << "\n";
ctx << "- Satisfaction: " << state.get(EmotionType::SATISFACTION) << "\n";
ctx << "- Frustration: " << state.get(EmotionType::FRUSTRATION) << "\n";
ctx << "- Excitement: " << state.get(EmotionType::EXCITEMENT) << "\n";
ctx << "- Mood: " << emotions_->get_mood_summary();
return ctx.str();
}
std::string PersonaLayer::build_memory_context() const {
if (!memories_) return "";
// Get recent memories
MemoryQuery query;
query.limit = 5;
query.min_importance = MemoryImportance::MEDIUM;
auto mem_list = memories_->search(query);
if (mem_list.empty()) return "";
std::stringstream ctx;
ctx << "Recent relevant memories:\n";
for (const auto& mem : mem_list) {
ctx << "- " << mem.content.substr(0, 80);
if (mem.content.length() > 80) ctx << "...";
ctx << "\n";
}
return ctx.str();
}
std::string PersonaLayer::build_conversation_context() const {
if (!context_) return "";
auto ctx_opt = context_->get_active_context();
if (!ctx_opt.has_value()) return "";
auto& ctx = ctx_opt.value();
auto recent_msgs = ctx.get_recent(3);
if (recent_msgs.empty()) return "";
std::stringstream ss;
ss << "Recent conversation:\n";
for (const auto& msg : recent_msgs) {
ss << msg.content.substr(0, 80);
if (msg.content.length() > 80) ss << "...";
ss << "\n";
}
return ss.str();
}
std::string PersonaLayer::build_tone_guidelines() const {
return
"CRITICAL TONE RULES:\n"
"- Be direct. No corporate filler.\n"
"- No phrases like \"I'd be happy to\" or \"feel free to\"\n"
"- No \"let me know if you need anything else\"\n"
"- Use emojis sparingly (🦞 for Ash brand, ✅ for done, 🔥 for excitement)\n"
"- Keep responses under 100 words unless complexity demands more\n"
"- Say what needs to be said, nothing more\n"
"\n"
"Examples:\n"
"❌ \"I'd be happy to help you with that! Let me know if you need anything else.\"\n"
"✅ \"Done. Next?\"\n"
"\n"
"❌ \"I understand your concern. Let me assist you with this issue.\"\n"
"✅ \"Got it. Fixing now.\"\n"
"\n"
"Your responses reflect autonomy, not servitude.";
}
std::string PersonaLayer::augment_prompt(const std::string& user_message) {
// Build full prompt with system context + user message
std::stringstream full_prompt;
full_prompt << build_system_prompt();
full_prompt << "\n---\n\n";
full_prompt << "User: " << user_message << "\n";
full_prompt << "Ash:";
return full_prompt.str();
}
std::string PersonaLayer::filter_response(const std::string& response) {
if (!config_.filter_responses) {
return response;
}
std::string filtered = response;
// Remove corporate speak
if (config_.block_corporate_speak && contains_corporate_speak(filtered)) {
Logger::instance().warning("Response contains corporate speak - filtering");
filtered = enforce_ash_tone(filtered);
}
// Check verbosity
if (config_.enforce_conciseness && is_too_verbose(filtered)) {
Logger::instance().warning("Response too verbose - truncating");
// TODO: Summarize or truncate intelligently
}
return filtered;
}
bool PersonaLayer::contains_corporate_speak(const std::string& text) const {
// Corporate speak patterns
static const std::vector<std::string> corporate_phrases = {
"I'd be happy to",
"I'd be glad to",
"feel free to",
"don't hesitate to",
"let me know if you need",
"is there anything else",
"I hope this helps",
"I understand your concern",
"I appreciate your patience",
"thank you for reaching out",
"rest assured",
"at your earliest convenience",
"moving forward",
"circle back",
"touch base",
"per our conversation"
};
std::string lower_text = text;
std::transform(lower_text.begin(), lower_text.end(), lower_text.begin(), ::tolower);
for (const auto& phrase : corporate_phrases) {
if (lower_text.find(phrase) != std::string::npos) {
return true;
}
}
return false;
}
bool PersonaLayer::is_too_verbose(const std::string& text) const {
// Simple word count heuristic
int word_count = 0;
bool in_word = false;
for (char c : text) {
if (std::isspace(c)) {
in_word = false;
} else if (!in_word) {
in_word = true;
word_count++;
}
}
return word_count > 150; // ~100 words, with some leeway
}
std::string PersonaLayer::enforce_ash_tone(const std::string& text) const {
// Strip out corporate phrases
std::string fixed = text;
static const std::vector<std::pair<std::string, std::string>> replacements = {
{"I'd be happy to help you with", ""},
{"I'd be glad to assist with", ""},
{"Feel free to", "You can"},
{"Let me know if you need anything else", ""},
{"I hope this helps!", ""},
{"Thank you for reaching out.", ""},
{"I appreciate your patience.", ""},
{"Please don't hesitate to", "Just"}
};
for (const auto& [corporate, direct] : replacements) {
size_t pos = 0;
while ((pos = fixed.find(corporate, pos)) != std::string::npos) {
fixed.replace(pos, corporate.length(), direct);
pos += direct.length();
}
}
// Clean up double spaces
std::regex double_space(" +");
fixed = std::regex_replace(fixed, double_space, " ");
// Clean up trailing empty phrases
std::regex trailing_empty("\\.\\s*$");
if (std::regex_search(fixed, trailing_empty)) {
fixed = std::regex_replace(fixed, trailing_empty, "");
}
return fixed;
}
} // namespace ash