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:bloc/bloc.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:gemini_app/api_key.dart';
|
||||||
import 'package:gemini_app/config.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:gemini_app/eeg/eeg_service.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:google_generative_ai/google_generative_ai.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
|
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 GeminiStatus { initial, loading, success, error }
|
||||||
|
|
||||||
// enum MessageType { text, image, audio, video }
|
// enum MessageType { text, image, audio, video }
|
||||||
@ -147,10 +151,11 @@ class GeminiCubit extends Cubit<GeminiState> {
|
|||||||
|
|
||||||
void startLesson() async {
|
void startLesson() async {
|
||||||
final quizQuestions = await loadQuizQuestions();
|
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 =
|
// 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";
|
// "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 =
|
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";
|
"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 = [
|
final safetySettings = [
|
||||||
@ -181,42 +186,51 @@ class GeminiCubit extends Cubit<GeminiState> {
|
|||||||
model: model);
|
model: model);
|
||||||
emit(initialState);
|
emit(initialState);
|
||||||
|
|
||||||
try {
|
sendMessage("");
|
||||||
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"));
|
|
||||||
|
|
||||||
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) {
|
// String responseText = '';
|
||||||
responseText += chunk.text ?? '';
|
|
||||||
emit(initialState.copyWith(
|
// await for (final chunk in stream) {
|
||||||
status: GeminiStatus.success,
|
// responseText += chunk.text ?? '';
|
||||||
messages: [
|
// emit(initialState.copyWith(
|
||||||
lessonScriptMessage,
|
// status: GeminiStatus.success,
|
||||||
Message(
|
// messages: [
|
||||||
source: MessageSource.agent,
|
// lessonScriptMessage,
|
||||||
text: responseText,
|
// Message(
|
||||||
type: MessageType.text)
|
// source: MessageSource.agent,
|
||||||
],
|
// text: responseText,
|
||||||
model: model));
|
// type: MessageType.text)
|
||||||
}
|
// ],
|
||||||
} catch (e) {
|
// model: model));
|
||||||
emit(GeminiState(
|
// }
|
||||||
status: GeminiStatus.error,
|
// } catch (e) {
|
||||||
messages: state.messages,
|
// emit(GeminiState(
|
||||||
error: e.toString(),
|
// status: GeminiStatus.error,
|
||||||
));
|
// messages: state.messages,
|
||||||
}
|
// error: e.toString(),
|
||||||
|
// ));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendMessage(String prompt) async {
|
void sendMessage(String prompt) async {
|
||||||
List<Message> messagesWithoutPrompt = state.messages;
|
List<Message> messagesWithoutPrompt = state.messages;
|
||||||
var messagesWithPrompt = state.messages +
|
List<Message> messagesWithPrompt;
|
||||||
[
|
if (prompt == "") {
|
||||||
Message(
|
messagesWithPrompt = state.messages;
|
||||||
text: prompt, type: MessageType.text, source: MessageSource.user)
|
} else {
|
||||||
];
|
messagesWithPrompt = state.messages +
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
text: prompt,
|
||||||
|
type: MessageType.text,
|
||||||
|
source: MessageSource.user)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
status: GeminiStatus.loading,
|
status: GeminiStatus.loading,
|
||||||
@ -233,17 +247,30 @@ class GeminiCubit extends Cubit<GeminiState> {
|
|||||||
|
|
||||||
String responseText = '';
|
String responseText = '';
|
||||||
|
|
||||||
|
bool isAnalysisDone = false;
|
||||||
|
|
||||||
await for (final chunk in stream) {
|
await for (final chunk in stream) {
|
||||||
responseText += chunk.text ?? '';
|
responseText += chunk.text ?? '';
|
||||||
emit(state.copyWith(
|
if (responseText.contains(LESSON_START_TOKEN)) {
|
||||||
status: GeminiStatus.success,
|
isAnalysisDone = true;
|
||||||
messages: messagesWithPrompt +
|
var startIndex = responseText.indexOf(LESSON_START_TOKEN) +
|
||||||
[
|
LESSON_START_TOKEN.length;
|
||||||
Message(
|
var analysisData = responseText.substring(0, startIndex);
|
||||||
source: MessageSource.agent,
|
print("ANALYSIS DATA: $analysisData");
|
||||||
text: responseText,
|
responseText =
|
||||||
type: MessageType.text)
|
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>")) {
|
if (responseText.contains("<QUIZ_START_TOKEN>")) {
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
const String geminiApiKey = '';
|
const String geminiApiKey = 'AIzaSyBU-vIDA4IUfRReXcu7Vdw53gnrnroJjzI';
|
||||||
const bool isDebug = true;
|
const bool isDebug = true;
|
||||||
|
@ -2,26 +2,24 @@ import 'dart:async';
|
|||||||
import 'package:gemini_app/config.dart';
|
import 'package:gemini_app/config.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
|
|
||||||
class EegState {
|
class EegState {
|
||||||
final double mind_wandering;
|
final double mindWandering;
|
||||||
final double focus;
|
final double focus;
|
||||||
|
|
||||||
EegState({
|
EegState({
|
||||||
required this.mind_wandering,
|
required this.mindWandering,
|
||||||
required this.focus,
|
required this.focus,
|
||||||
});
|
});
|
||||||
|
|
||||||
String getJsonString() {
|
String getJsonString() {
|
||||||
return '{"mind_wandering": $mind_wandering, "focus": $focus}';
|
return '{"mind_wandering": $mindWandering, "focus": $focus}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EegService {
|
class EegService {
|
||||||
EegState state;
|
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
|
// Start the timer when the cubit is created
|
||||||
if (!isDebug) {
|
if (!isDebug) {
|
||||||
startPolling();
|
startPolling();
|
||||||
@ -32,7 +30,7 @@ class EegService {
|
|||||||
|
|
||||||
void startPolling() {
|
void startPolling() {
|
||||||
// Poll every 1 second (adjust the duration as needed)
|
// 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
|
// Simulate getting new EEG data
|
||||||
// In a real application, you would fetch this data from your EEG device or API
|
// In a real application, you would fetch this data from your EEG device or API
|
||||||
// double newMindWandering = (DateTime.now().millisecondsSinceEpoch % 100) / 100;
|
// double newMindWandering = (DateTime.now().millisecondsSinceEpoch % 100) / 100;
|
||||||
@ -84,16 +82,16 @@ class EegService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void updateEegData(double mindWandering, double focus) {
|
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');
|
print('Mind Wandering: $mindWandering, Focus: $focus');
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleState() {
|
void toggleState() {
|
||||||
// Toggle the state between mind_wandering and focus
|
// Toggle the state between mind_wandering and focus
|
||||||
if (state.mind_wandering > state.focus) {
|
if (state.mindWandering > state.focus) {
|
||||||
updateEegData(state.focus, state.mind_wandering);
|
updateEegData(state.focus, state.mindWandering);
|
||||||
} else {
|
} else {
|
||||||
updateEegData(state.mind_wandering, state.focus);
|
updateEegData(state.mindWandering, state.focus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,14 +58,14 @@ class GeminiChatState extends State<GeminiChat> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _sendMessage() async {
|
void _sendMessage() async {
|
||||||
context
|
context.read<GeminiCubit>().sendMessage(_textController.text);
|
||||||
.read<GeminiCubit>()
|
|
||||||
.sendMessage(_textController.text);
|
|
||||||
_textController.clear();
|
_textController.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _toggleEegState() {
|
void _toggleEegState() {
|
||||||
_eegService.toggleState();
|
setState(() {
|
||||||
|
_eegService.toggleState();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _resetConversation() {
|
void _resetConversation() {
|
||||||
@ -91,20 +91,23 @@ class GeminiChatState extends State<GeminiChat> {
|
|||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Card(
|
Card(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Mind Wandering: ${_eegService.state.mind_wandering.toStringAsFixed(2)}'),
|
'Mind Wandering: ${_eegService.state.mindWandering.toStringAsFixed(2)}'),
|
||||||
Text('Focus: ${_eegService.state.focus.toStringAsFixed(2)}'),
|
Text(
|
||||||
],
|
'Focus: ${_eegService.state.focus.toStringAsFixed(2)}'),
|
||||||
),
|
],
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: BlocBuilder<GeminiCubit, GeminiState>(
|
child: BlocBuilder<GeminiCubit, GeminiState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@ -118,54 +121,87 @@ class GeminiChatState extends State<GeminiChat> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
BlocBuilder<GeminiCubit, GeminiState>(
|
BlocBuilder<GeminiCubit, GeminiState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return state.isQuizMode
|
return state.isQuizMode
|
||||||
? Container() // Hide text input in quiz mode
|
? Container()
|
||||||
: TextField(
|
: TextField(
|
||||||
controller: _textController,
|
controller: _textController,
|
||||||
decoration: const InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'Enter your message',
|
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(),
|
onSubmitted: (_) => _sendMessage(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
BlocBuilder<GeminiCubit, GeminiState>(
|
// BlocBuilder<GeminiCubit, GeminiState>(
|
||||||
builder: (context, state) {
|
// builder: (context, state) {
|
||||||
return state.isQuizMode
|
// return state.isQuizMode
|
||||||
? Container()
|
// ? Container()
|
||||||
: Expanded(
|
// : Expanded(
|
||||||
child: ElevatedButton(
|
// child: ElevatedButton(
|
||||||
onPressed: _sendMessage,
|
// onPressed: _sendMessage,
|
||||||
child: const Text('Send'),
|
// 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(
|
ElevatedButton(
|
||||||
onPressed: _resetConversation,
|
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(
|
ElevatedButton(
|
||||||
onPressed: _toggleEegState,
|
onPressed: _toggleEegState,
|
||||||
child: const Text('Toggle State'),
|
child: const Row(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
const SizedBox(width: 8),
|
children: [
|
||||||
BlocBuilder<GeminiCubit, GeminiState>(
|
Icon(Icons.toggle_on),
|
||||||
builder: (context, state) {
|
SizedBox(width: 3),
|
||||||
return state.isQuizMode
|
Text('Toggle State'),
|
||||||
? Container()
|
],
|
||||||
: ElevatedButton(
|
),
|
||||||
onPressed: _enterQuizMode,
|
|
||||||
child: const Text('Start Quiz'),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
// 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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: List.generate(3, (index) {
|
children: List.generate(3, (index) {
|
||||||
return AnimatedBuilder(
|
return AnimatedBuilder(
|
||||||
animation: _controllers[index],
|
animation: _controllers[index],
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Container(
|
return Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||||
padding: const EdgeInsets.all(2.5),
|
padding: const EdgeInsets.all(2.5),
|
||||||
child: Transform.translate(
|
child: Transform.translate(
|
||||||
offset: Offset(0, _animations[index].value),
|
offset: Offset(0, _animations[index].value),
|
||||||
|
@ -18,7 +18,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "2.11.0"
|
version: "2.11.0"
|
||||||
bloc:
|
bloc:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: bloc
|
name: bloc
|
||||||
sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
|
sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
|
||||||
@ -124,13 +124,13 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.3"
|
version: "0.4.3"
|
||||||
http:
|
http:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
|
sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.1"
|
version: "1.2.2"
|
||||||
http_parser:
|
http_parser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -42,6 +42,8 @@ dependencies:
|
|||||||
flutter_markdown: ^0.7.3
|
flutter_markdown: ^0.7.3
|
||||||
flutter_bloc: ^8.0.1
|
flutter_bloc: ^8.0.1
|
||||||
get_it: ^7.7.0
|
get_it: ^7.7.0
|
||||||
|
http: ^1.2.2
|
||||||
|
bloc: ^8.1.4
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Loading…
Reference in New Issue
Block a user