Code fixes, style, analysis separation
This commit is contained in:
parent
ff9cdc02d8
commit
ebededacc1
1
lib/api_key.dart
Normal file
1
lib/api_key.dart
Normal file
@ -0,0 +1 @@
|
||||
const String geminiApiKey = '';
|
@ -0,0 +1 @@
|
||||
|
@ -2,8 +2,8 @@ import 'dart:convert';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:gemini_app/api_key.dart';
|
||||
import 'package:gemini_app/config.dart';
|
||||
import 'package:gemini_app/bloc/eeg_state.dart';
|
||||
import 'package:gemini_app/eeg/eeg_service.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:google_generative_ai/google_generative_ai.dart';
|
||||
@ -23,6 +23,10 @@ here describe what is the state of the student and how to best approach them
|
||||
here continue with the lesson, respond to answers, etc
|
||||
""";
|
||||
|
||||
const String LESSON_START_TOKEN = "<LESSON_START_TOKEN>";
|
||||
const String ANALYSIS_START_TOKEN = "<ANALYSIS_START_TOKEN>";
|
||||
const String QUIZ_START_TOKEN = "<QUIZ_START_TOKEN>";
|
||||
|
||||
enum GeminiStatus { initial, loading, success, error }
|
||||
|
||||
// enum MessageType { text, image, audio, video }
|
||||
@ -147,10 +151,11 @@ class GeminiCubit extends Cubit<GeminiState> {
|
||||
|
||||
void startLesson() async {
|
||||
final quizQuestions = await loadQuizQuestions();
|
||||
final String lessonScript = await rootBundle.loadString('assets/lessons/cells.md');
|
||||
final String lessonScript =
|
||||
await rootBundle.loadString('assets/lessons/cells.md');
|
||||
// final String prompt =
|
||||
// "Jesteś nauczycielem/chatbotem prowadzącym zajęcia z jednym uczniem. Uczeń ma możliwość zadawania pytań w trakcie, natomiast jesteś odpowiedzialny za prowadzenie lekcji i przedstawienie tematu. Zacznij prowadzić lekcje dla jednego ucznia na podstawie poniszego skryptu:\n$rjp";
|
||||
final String prompt =
|
||||
// "Jesteś nauczycielem/chatbotem prowadzącym zajęcia z jednym uczniem. Uczeń ma możliwość zadawania pytań w trakcie, natomiast jesteś odpowiedzialny za prowadzenie lekcji i przedstawienie tematu. Zacznij prowadzić lekcje dla jednego ucznia na podstawie poniszego skryptu:\n$rjp";
|
||||
final String prompt =
|
||||
"You are a teacher/chatbot conducting a class with one student. The student has the ability to ask questions during the lesson, while you are responsible for leading the class and presenting the topic. Start conducting the lesson for one student based on the script below:\n$lessonScript";
|
||||
|
||||
final safetySettings = [
|
||||
@ -181,42 +186,51 @@ class GeminiCubit extends Cubit<GeminiState> {
|
||||
model: model);
|
||||
emit(initialState);
|
||||
|
||||
try {
|
||||
final chat = state.model!.startChat(history: [Content.text(prompt)]);
|
||||
final stream = chat.sendMessageStream(Content.text(
|
||||
"EEG DATA:\n${GetIt.instance<EegService>().state.getJsonString()}\nMessage:\n$prompt"));
|
||||
sendMessage("");
|
||||
|
||||
String responseText = '';
|
||||
// try {
|
||||
// final chat = state.model!.startChat(history: [Content.text(prompt)]);
|
||||
// final stream = chat.sendMessageStream(Content.text(
|
||||
// "EEG DATA:\n${GetIt.instance<EegService>().state.getJsonString()}\nMessage:\n$prompt"));
|
||||
|
||||
await for (final chunk in stream) {
|
||||
responseText += chunk.text ?? '';
|
||||
emit(initialState.copyWith(
|
||||
status: GeminiStatus.success,
|
||||
messages: [
|
||||
lessonScriptMessage,
|
||||
Message(
|
||||
source: MessageSource.agent,
|
||||
text: responseText,
|
||||
type: MessageType.text)
|
||||
],
|
||||
model: model));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(GeminiState(
|
||||
status: GeminiStatus.error,
|
||||
messages: state.messages,
|
||||
error: e.toString(),
|
||||
));
|
||||
}
|
||||
// String responseText = '';
|
||||
|
||||
// await for (final chunk in stream) {
|
||||
// responseText += chunk.text ?? '';
|
||||
// emit(initialState.copyWith(
|
||||
// status: GeminiStatus.success,
|
||||
// messages: [
|
||||
// lessonScriptMessage,
|
||||
// Message(
|
||||
// source: MessageSource.agent,
|
||||
// text: responseText,
|
||||
// type: MessageType.text)
|
||||
// ],
|
||||
// model: model));
|
||||
// }
|
||||
// } catch (e) {
|
||||
// emit(GeminiState(
|
||||
// status: GeminiStatus.error,
|
||||
// messages: state.messages,
|
||||
// error: e.toString(),
|
||||
// ));
|
||||
// }
|
||||
}
|
||||
|
||||
void sendMessage(String prompt) async {
|
||||
List<Message> messagesWithoutPrompt = state.messages;
|
||||
var messagesWithPrompt = state.messages +
|
||||
[
|
||||
Message(
|
||||
text: prompt, type: MessageType.text, source: MessageSource.user)
|
||||
];
|
||||
List<Message> messagesWithPrompt;
|
||||
if (prompt == "") {
|
||||
messagesWithPrompt = state.messages;
|
||||
} else {
|
||||
messagesWithPrompt = state.messages +
|
||||
[
|
||||
Message(
|
||||
text: prompt,
|
||||
type: MessageType.text,
|
||||
source: MessageSource.user)
|
||||
];
|
||||
}
|
||||
|
||||
emit(state.copyWith(
|
||||
status: GeminiStatus.loading,
|
||||
@ -233,17 +247,30 @@ class GeminiCubit extends Cubit<GeminiState> {
|
||||
|
||||
String responseText = '';
|
||||
|
||||
bool isAnalysisDone = false;
|
||||
|
||||
await for (final chunk in stream) {
|
||||
responseText += chunk.text ?? '';
|
||||
emit(state.copyWith(
|
||||
status: GeminiStatus.success,
|
||||
messages: messagesWithPrompt +
|
||||
[
|
||||
Message(
|
||||
source: MessageSource.agent,
|
||||
text: responseText,
|
||||
type: MessageType.text)
|
||||
]));
|
||||
if (responseText.contains(LESSON_START_TOKEN)) {
|
||||
isAnalysisDone = true;
|
||||
var startIndex = responseText.indexOf(LESSON_START_TOKEN) +
|
||||
LESSON_START_TOKEN.length;
|
||||
var analysisData = responseText.substring(0, startIndex);
|
||||
print("ANALYSIS DATA: $analysisData");
|
||||
responseText =
|
||||
responseText.substring(startIndex, responseText.length);
|
||||
}
|
||||
if (isAnalysisDone) {
|
||||
emit(state.copyWith(
|
||||
status: GeminiStatus.success,
|
||||
messages: messagesWithPrompt +
|
||||
[
|
||||
Message(
|
||||
source: MessageSource.agent,
|
||||
text: responseText,
|
||||
type: MessageType.text)
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
if (responseText.contains("<QUIZ_START_TOKEN>")) {
|
||||
|
@ -1,2 +1,2 @@
|
||||
const String geminiApiKey = '';
|
||||
const String geminiApiKey = 'AIzaSyBU-vIDA4IUfRReXcu7Vdw53gnrnroJjzI';
|
||||
const bool isDebug = true;
|
||||
|
@ -2,26 +2,24 @@ import 'dart:async';
|
||||
import 'package:gemini_app/config.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class EegState {
|
||||
final double mind_wandering;
|
||||
final double mindWandering;
|
||||
final double focus;
|
||||
|
||||
EegState({
|
||||
required this.mind_wandering,
|
||||
required this.mindWandering,
|
||||
required this.focus,
|
||||
});
|
||||
|
||||
String getJsonString() {
|
||||
return '{"mind_wandering": $mind_wandering, "focus": $focus}';
|
||||
return '{"mind_wandering": $mindWandering, "focus": $focus}';
|
||||
}
|
||||
}
|
||||
|
||||
class EegService {
|
||||
EegState state;
|
||||
|
||||
EegService() : state = EegState(mind_wandering: 0.9, focus: 0.1) {
|
||||
EegService() : state = EegState(mindWandering: 0.9, focus: 0.1) {
|
||||
// Start the timer when the cubit is created
|
||||
if (!isDebug) {
|
||||
startPolling();
|
||||
@ -32,7 +30,7 @@ class EegService {
|
||||
|
||||
void startPolling() {
|
||||
// Poll every 1 second (adjust the duration as needed)
|
||||
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
// Simulate getting new EEG data
|
||||
// In a real application, you would fetch this data from your EEG device or API
|
||||
// double newMindWandering = (DateTime.now().millisecondsSinceEpoch % 100) / 100;
|
||||
@ -84,16 +82,16 @@ class EegService {
|
||||
}
|
||||
|
||||
void updateEegData(double mindWandering, double focus) {
|
||||
state = EegState(mind_wandering: mindWandering, focus: focus);
|
||||
state = EegState(mindWandering: mindWandering, focus: focus);
|
||||
print('Mind Wandering: $mindWandering, Focus: $focus');
|
||||
}
|
||||
|
||||
void toggleState() {
|
||||
// Toggle the state between mind_wandering and focus
|
||||
if (state.mind_wandering > state.focus) {
|
||||
updateEegData(state.focus, state.mind_wandering);
|
||||
if (state.mindWandering > state.focus) {
|
||||
updateEegData(state.focus, state.mindWandering);
|
||||
} else {
|
||||
updateEegData(state.mind_wandering, state.focus);
|
||||
updateEegData(state.mindWandering, state.focus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,14 +58,14 @@ class GeminiChatState extends State<GeminiChat> {
|
||||
}
|
||||
|
||||
void _sendMessage() async {
|
||||
context
|
||||
.read<GeminiCubit>()
|
||||
.sendMessage(_textController.text);
|
||||
context.read<GeminiCubit>().sendMessage(_textController.text);
|
||||
_textController.clear();
|
||||
}
|
||||
|
||||
void _toggleEegState() {
|
||||
_eegService.toggleState();
|
||||
setState(() {
|
||||
_eegService.toggleState();
|
||||
});
|
||||
}
|
||||
|
||||
void _resetConversation() {
|
||||
@ -91,20 +91,23 @@ class GeminiChatState extends State<GeminiChat> {
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Mind Wandering: ${_eegService.state.mind_wandering.toStringAsFixed(2)}'),
|
||||
Text('Focus: ${_eegService.state.focus.toStringAsFixed(2)}'),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Mind Wandering: ${_eegService.state.mindWandering.toStringAsFixed(2)}'),
|
||||
Text(
|
||||
'Focus: ${_eegService.state.focus.toStringAsFixed(2)}'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Expanded(
|
||||
child: BlocBuilder<GeminiCubit, GeminiState>(
|
||||
builder: (context, state) {
|
||||
@ -118,54 +121,87 @@ class GeminiChatState extends State<GeminiChat> {
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
BlocBuilder<GeminiCubit, GeminiState>(
|
||||
builder: (context, state) {
|
||||
return state.isQuizMode
|
||||
? Container() // Hide text input in quiz mode
|
||||
? Container()
|
||||
: TextField(
|
||||
controller: _textController,
|
||||
decoration: const InputDecoration(
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Enter your message',
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
),
|
||||
filled: true,
|
||||
fillColor: Colors.grey[200],
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0, vertical: 12.0),
|
||||
),
|
||||
onSubmitted: (_) => _sendMessage(),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
BlocBuilder<GeminiCubit, GeminiState>(
|
||||
builder: (context, state) {
|
||||
return state.isQuizMode
|
||||
? Container()
|
||||
: Expanded(
|
||||
child: ElevatedButton(
|
||||
onPressed: _sendMessage,
|
||||
child: const Text('Send'),
|
||||
),
|
||||
);
|
||||
},
|
||||
// BlocBuilder<GeminiCubit, GeminiState>(
|
||||
// builder: (context, state) {
|
||||
// return state.isQuizMode
|
||||
// ? Container()
|
||||
// : Expanded(
|
||||
// child: ElevatedButton(
|
||||
// onPressed: _sendMessage,
|
||||
// child: const Text('Send'),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
ElevatedButton(
|
||||
onPressed: _sendMessage,
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.send),
|
||||
SizedBox(width: 3),
|
||||
Text('Send'),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
|
||||
ElevatedButton(
|
||||
onPressed: _resetConversation,
|
||||
child: const Text('Reset'),
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.refresh),
|
||||
SizedBox(width: 3),
|
||||
Text('Reset'),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
ElevatedButton(
|
||||
onPressed: _toggleEegState,
|
||||
child: const Text('Toggle State'),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
BlocBuilder<GeminiCubit, GeminiState>(
|
||||
builder: (context, state) {
|
||||
return state.isQuizMode
|
||||
? Container()
|
||||
: ElevatedButton(
|
||||
onPressed: _enterQuizMode,
|
||||
child: const Text('Start Quiz'),
|
||||
);
|
||||
},
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.toggle_on),
|
||||
SizedBox(width: 3),
|
||||
Text('Toggle State'),
|
||||
],
|
||||
),
|
||||
),
|
||||
// ElevatedButton(
|
||||
// onPressed: _enterQuizMode,
|
||||
// child: const Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// Icon(Icons.quiz),
|
||||
// SizedBox(width: 8),
|
||||
// Text('Start Quiz'),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
],
|
||||
@ -302,12 +338,13 @@ class BouncingDotsState extends State<BouncingDots>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: List.generate(3, (index) {
|
||||
return AnimatedBuilder(
|
||||
animation: _controllers[index],
|
||||
builder: (context, child) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||
padding: const EdgeInsets.all(2.5),
|
||||
child: Transform.translate(
|
||||
offset: Offset(0, _animations[index].value),
|
||||
|
@ -18,7 +18,7 @@ packages:
|
||||
source: hosted
|
||||
version: "2.11.0"
|
||||
bloc:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: bloc
|
||||
sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
|
||||
@ -124,13 +124,13 @@ packages:
|
||||
source: hosted
|
||||
version: "0.4.3"
|
||||
http:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
|
||||
sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
version: "1.2.2"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -42,6 +42,8 @@ dependencies:
|
||||
flutter_markdown: ^0.7.3
|
||||
flutter_bloc: ^8.0.1
|
||||
get_it: ^7.7.0
|
||||
http: ^1.2.2
|
||||
bloc: ^8.1.4
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
Reference in New Issue
Block a user