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,7 +151,8 @@ 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 =
|
||||
@ -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 +
|
||||
List<Message> messagesWithPrompt;
|
||||
if (prompt == "") {
|
||||
messagesWithPrompt = state.messages;
|
||||
} else {
|
||||
messagesWithPrompt = state.messages +
|
||||
[
|
||||
Message(
|
||||
text: prompt, type: MessageType.text, source: MessageSource.user)
|
||||
text: prompt,
|
||||
type: MessageType.text,
|
||||
source: MessageSource.user)
|
||||
];
|
||||
}
|
||||
|
||||
emit(state.copyWith(
|
||||
status: GeminiStatus.loading,
|
||||
@ -233,8 +247,20 @@ class GeminiCubit extends Cubit<GeminiState> {
|
||||
|
||||
String responseText = '';
|
||||
|
||||
bool isAnalysisDone = false;
|
||||
|
||||
await for (final chunk in stream) {
|
||||
responseText += chunk.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 +
|
||||
@ -245,6 +271,7 @@ class GeminiCubit extends Cubit<GeminiState> {
|
||||
type: MessageType.text)
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
if (responseText.contains("<QUIZ_START_TOKEN>")) {
|
||||
enterQuizMode();
|
||||
|
@ -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() {
|
||||
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),
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Mind Wandering: ${_eegService.state.mind_wandering.toStringAsFixed(2)}'),
|
||||
Text('Focus: ${_eegService.state.focus.toStringAsFixed(2)}'),
|
||||
'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(
|
||||
// BlocBuilder<GeminiCubit, GeminiState>(
|
||||
// builder: (context, state) {
|
||||
// return state.isQuizMode
|
||||
// ? Container()
|
||||
// : Expanded(
|
||||
// child: ElevatedButton(
|
||||
// onPressed: _sendMessage,
|
||||
// child: const Text('Send'),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
ElevatedButton(
|
||||
onPressed: _sendMessage,
|
||||
child: const Text('Send'),
|
||||
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'),
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.toggle_on),
|
||||
SizedBox(width: 3),
|
||||
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'),
|
||||
);
|
||||
},
|
||||
),
|
||||
// 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