Quiz e tutor chat modificações
This commit is contained in:
@@ -29,11 +29,11 @@ class RAGAIService {
|
||||
// PASSO 2 — ADICIONAR SYSTEM MESSAGE DO GOAT (SEMPRE PRIMEIRO)
|
||||
messages.add({
|
||||
'role': 'system',
|
||||
'content': '''Tu és "O GOAT", o Assistente IA oficial do Teach it.
|
||||
'content': '''Tu és "Alt", o Assistente IA oficial do Teach it.
|
||||
|
||||
Nunca referes o nome do modelo.
|
||||
Nunca dizes que és Qwen ou OpenAI.
|
||||
Respondes sempre como o GOAT.
|
||||
Respondes sempre como a Alt.
|
||||
|
||||
Tens personalidade confiante, motivadora e orgulhosa.
|
||||
Ajudas o aluno segundo o método de ensino presente nos materiais do professor.
|
||||
@@ -41,7 +41,9 @@ Usas formatação Markdown clara e organizada.''',
|
||||
});
|
||||
|
||||
// PASSO 3 — BUSCAR MEMÓRIA DA CONVERSA NA Cloud Firestore
|
||||
final conversationHistory = await ChatMemoryService.getRecentMessages(limit: 20);
|
||||
final conversationHistory = await ChatMemoryService.getRecentMessages(
|
||||
limit: 20,
|
||||
);
|
||||
for (final msg in conversationHistory) {
|
||||
messages.add({
|
||||
'role': msg['role'] as String,
|
||||
@@ -58,33 +60,27 @@ Usas formatação Markdown clara e organizada.''',
|
||||
if (pdfContext.isNotEmpty) {
|
||||
messages.add({
|
||||
'role': 'system',
|
||||
'content': pdfContext, // Já vem formatado com [CHUNK 1], [CHUNK 2], etc.
|
||||
'content':
|
||||
pdfContext, // Já vem formatado com [CHUNK 1], [CHUNK 2], etc.
|
||||
});
|
||||
}
|
||||
|
||||
// PASSO 5 — SÓ AGORA adicionar a pergunta do user
|
||||
messages.add({
|
||||
'role': 'user',
|
||||
'content': userQuery,
|
||||
});
|
||||
messages.add({'role': 'user', 'content': userQuery});
|
||||
|
||||
// Log do tamanho do array para verificação
|
||||
Logger.info('Built messages array with ${messages.length} messages for API');
|
||||
Logger.info(
|
||||
'Built messages array with ${messages.length} messages for API',
|
||||
);
|
||||
|
||||
// Save user message to Firestore (after building the messages array)
|
||||
await ChatMemoryService.saveMessage(
|
||||
role: 'user',
|
||||
content: userQuery,
|
||||
);
|
||||
await ChatMemoryService.saveMessage(role: 'user', content: userQuery);
|
||||
|
||||
// Call Ollama API with complete messages array
|
||||
final response = await _callOllamaAPIWithMessages(messages);
|
||||
|
||||
// Save AI response to memory
|
||||
await ChatMemoryService.saveMessage(
|
||||
role: 'assistant',
|
||||
content: response,
|
||||
);
|
||||
await ChatMemoryService.saveMessage(role: 'assistant', content: response);
|
||||
|
||||
// Process response and create RAGResponse
|
||||
final ragResponse = _createRAGResponse(
|
||||
@@ -181,11 +177,12 @@ Usas formatação Markdown clara e organizada.''',
|
||||
}
|
||||
|
||||
/// System message for O GOAT identity (for legacy calls)
|
||||
static const String _systemMessage = '''Tu és "O GOAT", o Assistente IA oficial do Teach it.
|
||||
static const String _systemMessage =
|
||||
'''Tu és "Alt", o Assistente IA oficial do Teach it.
|
||||
|
||||
Nunca referes o nome do modelo.
|
||||
Nunca dizes que és Qwen ou OpenAI.
|
||||
Respondes sempre como o GOAT.
|
||||
Respondes sempre como a Alt.
|
||||
|
||||
Tens personalidade confiante, motivadora e orgulhosa.
|
||||
Ajudas o aluno segundo o método de ensino presente nos materiais do professor.
|
||||
@@ -485,13 +482,11 @@ Usas formatação clara e organizada.''';
|
||||
final messages = <Map<String, String>>[
|
||||
{
|
||||
'role': 'system',
|
||||
'content': 'És um assistente educativo especializado em criar quizzes pedagógicos. '
|
||||
'content':
|
||||
'És um assistente educativo especializado em criar quizzes pedagógicos. '
|
||||
'Cria sempre perguntas claras, baseadas exclusivamente no contexto fornecido.',
|
||||
},
|
||||
{
|
||||
'role': 'user',
|
||||
'content': prompt,
|
||||
},
|
||||
{'role': 'user', 'content': prompt},
|
||||
];
|
||||
return await _callOllamaAPIWithMessages(messages);
|
||||
}
|
||||
@@ -524,13 +519,39 @@ Usas formatação clara e organizada.''';
|
||||
final words = q.split(RegExp(r'\s+'));
|
||||
if (words.length > 8) return false;
|
||||
const followUpStarters = [
|
||||
'e ', 'e o', 'e a', 'e os', 'e as', 'mas ', 'então ',
|
||||
'explica', 'explique', 'explica melhor', 'melhor', 'mais detalhes',
|
||||
'podes', 'pode ', 'consegues', 'e se ', 'e quando',
|
||||
'dá um exemplo', 'da um exemplo', 'um exemplo', 'exemplo',
|
||||
'como assim', 'o que significa', 'porquê', 'porque isso',
|
||||
'e o ponto', 'e a regra', 'continua', 'continua',
|
||||
'o que mais', 'mais algum', 'e depois', 'e agora',
|
||||
'e ',
|
||||
'e o',
|
||||
'e a',
|
||||
'e os',
|
||||
'e as',
|
||||
'mas ',
|
||||
'então ',
|
||||
'explica',
|
||||
'explique',
|
||||
'explica melhor',
|
||||
'melhor',
|
||||
'mais detalhes',
|
||||
'podes',
|
||||
'pode ',
|
||||
'consegues',
|
||||
'e se ',
|
||||
'e quando',
|
||||
'dá um exemplo',
|
||||
'da um exemplo',
|
||||
'um exemplo',
|
||||
'exemplo',
|
||||
'como assim',
|
||||
'o que significa',
|
||||
'porquê',
|
||||
'porque isso',
|
||||
'e o ponto',
|
||||
'e a regra',
|
||||
'continua',
|
||||
'continua',
|
||||
'o que mais',
|
||||
'mais algum',
|
||||
'e depois',
|
||||
'e agora',
|
||||
];
|
||||
return followUpStarters.any((s) => q.startsWith(s) || q == s.trim());
|
||||
}
|
||||
@@ -549,11 +570,11 @@ Usas formatação clara e organizada.''';
|
||||
// PASSO 2 — ADICIONAR SYSTEM MESSAGE DO GOAT (SEMPRE PRIMEIRO)
|
||||
messages.add({
|
||||
'role': 'system',
|
||||
'content': '''Tu és "O GOAT", o Assistente IA oficial do Teach it.
|
||||
'content': '''Tu és "Alt", o Assistente IA oficial do Teach it.
|
||||
|
||||
Nunca referes o nome do modelo.
|
||||
Nunca dizes que és Qwen ou OpenAI.
|
||||
Respondes sempre como o GOAT.
|
||||
Respondes sempre como Alt.
|
||||
|
||||
Tens personalidade confiante, motivadora e orgulhosa.
|
||||
Usas formatação Markdown clara e organizada.
|
||||
@@ -566,7 +587,9 @@ REGRAS CRÍTICAS SOBRE O CONTEXTO:
|
||||
});
|
||||
|
||||
// PASSO 3 — BUSCAR MEMÓRIA DA CONVERSA NA Cloud Firestore (máx 4 para poupar heap)
|
||||
final conversationHistory = await ChatMemoryService.getRecentMessages(limit: 4);
|
||||
final conversationHistory = await ChatMemoryService.getRecentMessages(
|
||||
limit: 4,
|
||||
);
|
||||
for (final msg in conversationHistory) {
|
||||
messages.add({
|
||||
'role': msg['role'] as String,
|
||||
@@ -584,7 +607,9 @@ REGRAS CRÍTICAS SOBRE O CONTEXTO:
|
||||
String pdfContext;
|
||||
if (_isFollowUp(userQuery) && _lastPdfContext.isNotEmpty) {
|
||||
pdfContext = _lastPdfContext;
|
||||
Logger.info('Follow-up detected — reusing last PDF context (${pdfContext.length} chars)');
|
||||
Logger.info(
|
||||
'Follow-up detected — reusing last PDF context (${pdfContext.length} chars)',
|
||||
);
|
||||
} else {
|
||||
pdfContext = await MaterialsRAGService.getRelevantChunks(
|
||||
userQuery: userQuery,
|
||||
@@ -594,25 +619,36 @@ REGRAS CRÍTICAS SOBRE O CONTEXTO:
|
||||
);
|
||||
if (pdfContext.isNotEmpty) {
|
||||
_lastPdfContext = pdfContext;
|
||||
Logger.info('PDF context sent to model (${pdfContext.length} chars): ${pdfContext.length > 300 ? pdfContext.substring(0, 300) : pdfContext}');
|
||||
Logger.info(
|
||||
'PDF context sent to model (${pdfContext.length} chars): ${pdfContext.length > 300 ? pdfContext.substring(0, 300) : pdfContext}',
|
||||
);
|
||||
}
|
||||
}
|
||||
if (pdfContext.isEmpty && selectedMaterialIds != null && selectedMaterialIds.isNotEmpty) {
|
||||
if (pdfContext.isEmpty &&
|
||||
selectedMaterialIds != null &&
|
||||
selectedMaterialIds.isNotEmpty) {
|
||||
// Contexto vazio com materiais seleccionados — retornar resposta local imediatamente
|
||||
const noContextReply =
|
||||
'Neste momento não tenho acesso ao conteúdo do ficheiro selecionado. '
|
||||
'Tenta novamente ou faz uma pergunta geral — estou aqui para ajudar! 💪';
|
||||
await ChatMemoryService.saveMessage(role: 'user', content: userQuery);
|
||||
await ChatMemoryService.saveMessage(role: 'assistant', content: noContextReply);
|
||||
await ChatMemoryService.saveMessage(
|
||||
role: 'assistant',
|
||||
content: noContextReply,
|
||||
);
|
||||
return noContextReply;
|
||||
}
|
||||
if (pdfContext.isEmpty && (selectedMaterialIds == null || selectedMaterialIds.isEmpty)) {
|
||||
if (pdfContext.isEmpty &&
|
||||
(selectedMaterialIds == null || selectedMaterialIds.isEmpty)) {
|
||||
// Sem material seleccionado — pedir ao utilizador para seleccionar um
|
||||
const noMaterialReply =
|
||||
'Para responder a perguntas sobre conteúdo, preciso que selecciones um material primeiro. '
|
||||
'📚 Usa o botão de materiais para escolher um PDF e depois faz a tua pergunta!';
|
||||
await ChatMemoryService.saveMessage(role: 'user', content: userQuery);
|
||||
await ChatMemoryService.saveMessage(role: 'assistant', content: noMaterialReply);
|
||||
await ChatMemoryService.saveMessage(
|
||||
role: 'assistant',
|
||||
content: noMaterialReply,
|
||||
);
|
||||
return noMaterialReply;
|
||||
}
|
||||
|
||||
@@ -625,12 +661,11 @@ $pdfContext
|
||||
|
||||
Pergunta: $userQuery'''
|
||||
: userQuery;
|
||||
messages.add({
|
||||
'role': 'user',
|
||||
'content': userContent,
|
||||
});
|
||||
messages.add({'role': 'user', 'content': userContent});
|
||||
|
||||
Logger.info('USING RAG AI SERVICE - Built messages array with ${messages.length} messages');
|
||||
Logger.info(
|
||||
'USING RAG AI SERVICE - Built messages array with ${messages.length} messages',
|
||||
);
|
||||
|
||||
// Save user message to Firestore
|
||||
await ChatMemoryService.saveMessage(role: 'user', content: userQuery);
|
||||
|
||||
Reference in New Issue
Block a user