Skip to content

Commit

Permalink
[refactor] [http] api_calls file refactor, and api_manager removed (#90)
Browse files Browse the repository at this point in the history
Simplified HTTP interactions
Removed all the boilerplate code from FlutterFlow
Same functionality, but that previous code was terrible, and impossible
to work on top of it
  • Loading branch information
josancamon19 committed Apr 30, 2024
2 parents b616f39 + 3f536e0 commit 630ee59
Show file tree
Hide file tree
Showing 19 changed files with 518 additions and 1,215 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -79,3 +79,4 @@ apps/AppWithWearable/ios/Runner/GeneratedPluginRegistrant.m
apps/AppWithWearable/macos/Flutter/ephemeral/flutter_export_environment.sh
apps/AppWithWearable/macos/Flutter/ephemeral/Flutter-Generated.xcconfig
apps/AppStandalone/ios/Runner/RunnerDebug.entitlements
apps/AppStandalone/lib/firebase_options.dart
2 changes: 0 additions & 2 deletions apps/AppStandalone/.env.template
Expand Up @@ -11,5 +11,3 @@ FIREBASE_STORAGE_BUCKET=
FIREBASE_MESSAGE_SENDER_ID=
FIREBASE_APP_ID=
FIREBASE_MEASUREMENT_ID=
SUPABASE_URL=
SUPABASE_ANON_KEY=
150 changes: 63 additions & 87 deletions apps/AppStandalone/lib/actions/actions.dart
Expand Up @@ -10,38 +10,29 @@ import '/flutter_flow/custom_functions.dart' as functions;

// Process the creation of memory records
Future<void> memoryCreationBlock(BuildContext context) async {
var structuredMemoryResponse = await structureMemory();
if (functions.memoryContainsNA(extractContent(structuredMemoryResponse))) {
await saveFailureMemory(structuredMemoryResponse);
var structuredMemory = await structureMemory();
debugPrint('Structured Memory: $structuredMemory');
if (functions.memoryContainsNA(structuredMemory)) {
await saveFailureMemory(structuredMemory);
} else {
await processStructuredMemory(structuredMemoryResponse);
await processStructuredMemory(structuredMemory);
}
}

// Call to the API to get structured memory
Future<ApiCallResponse> structureMemory() async {
Future<String> structureMemory() async {
logFirebaseEvent('memoryCreationBlock_StructureMemoryAPI');
return await StructuredMemoryCall.call(
memory: functions.jsonEncodeString(FFAppState().lastMemory),
);
}

// Extract content from API response
String extractContent(ApiCallResponse response) {
return getJsonField(
(response.jsonBody ?? ''),
r'''$.choices[0].message.content''',
).toString();
return await fetchStructuredMemory(FFAppState().lastMemory);
}

// Save failure memory when structured memory contains NA
Future<void> saveFailureMemory(ApiCallResponse response) async {
Future<void> saveFailureMemory(String structuredMemory) async {
logFirebaseEvent('memoryCreationBlock_backend_call');
await MemoriesRecord.collection.doc().set({
...createMemoriesRecordData(
memory: FFAppState().lastMemory,
user: currentUserReference,
structuredMemory: extractContent(response),
structuredMemory: structuredMemory,
feedback: '',
toShowToUserShowHide: 'Hide',
emptyMemory: FFAppState().lastMemory == '',
Expand All @@ -54,17 +45,26 @@ Future<void> saveFailureMemory(ApiCallResponse response) async {
}

// Process structured memory when it's valid
Future<void> processStructuredMemory(ApiCallResponse response) async {
if (functions.xGreaterThany(functions.wordCount(FFAppState().lastMemory), 1)!) {
Future<void> processStructuredMemory(String structuredMemory) async {
debugPrint('processStructuredMemory: $structuredMemory');
debugPrint('processStructuredMemory: ${functions.wordCount(FFAppState().lastMemory)}');

if (functions.wordCount(FFAppState().lastMemory) > 1) {
updateAppStateForProcessing();
var feedbackResponse = await requestFeedback(response);
await evaluateFeedback(feedbackResponse);
updateFinalAppState(feedbackResponse);
var feedback = await requestFeedback(structuredMemory);
var isFeedbackUseful = await evaluateFeedback(feedback);
debugPrint('Feedback: $feedback');
debugPrint('isFeedbackUseful: $isFeedbackUseful');
updateFinalAppState(feedback, isFeedbackUseful);
} else {
updateAppStateForEmptyFeedback();
}
logFirebaseEvent('memoryCreationBlock_backend_call', parameters: buildLogParameters(response));
await finalizeMemoryRecord(response);
logFirebaseEvent('memoryCreationBlock_backend_call', parameters: {
'jsonBody': (structuredMemory),
'memory': FFAppState().lastMemory,
'user': currentUserReference,
});
await finalizeMemoryRecord(structuredMemory);
}

// Update app state when starting memory processing
Expand All @@ -76,33 +76,26 @@ void updateAppStateForProcessing() {
}

// Request feedback for the given memory
Future<ApiCallResponse> requestFeedback(ApiCallResponse structuredMemoryResponse) async {
Future<String> requestFeedback(String structuredMemory) async {
logFirebaseEvent('memoryCreationBlock_FEEDBACKapi');
return await ChatGPTFeedbackCall.call(
memory: functions.jsonEncodeString(FFAppState().lastMemory),
structuredMemory: functions.jsonEncodeString(extractContent(structuredMemoryResponse)),
);
return await getGPTFeedback(FFAppState().lastMemory, structuredMemory);
}

// Evaluate feedback usefulness
Future<void> evaluateFeedback(ApiCallResponse feedbackResponse) async {
Future<String> evaluateFeedback(String feedback) async {
logFirebaseEvent('memoryCreationBlock_custom_action');
await actions.debugLog(extractContent(feedbackResponse));
logFirebaseEvent('memoryCreationBlock_backend_call');
await IsFeeedbackUsefulCall.call(
memory: FFAppState().lastMemory,
feedback: extractContent(feedbackResponse),
);
return await isFeedbackUseful(FFAppState().lastMemory, feedback);
}

// Update app state after processing feedback
void updateFinalAppState(ApiCallResponse feedbackResponse) {
void updateFinalAppState(String feedback, String isFeedbackUseful) {
logFirebaseEvent('memoryCreationBlock_update_app_state');
FFAppState().update(() {
FFAppState().feedback = functions.jsonEncodeString(extractContent(feedbackResponse))!;
FFAppState().isFeedbackUseful = functions.jsonEncodeString(extractContent(feedbackResponse))!;
FFAppState().chatHistory = functions.saveChatHistory(
FFAppState().chatHistory, functions.convertToJSONRole(extractContent(feedbackResponse), 'assistant'));
FFAppState().feedback = feedback;
FFAppState().isFeedbackUseful = isFeedbackUseful;
FFAppState().chatHistory =
functions.saveChatHistory(FFAppState().chatHistory, functions.convertToJSONRole(feedback, 'assistant'));
FFAppState().memoryCreationProcessing = false;
});
}
Expand All @@ -116,80 +109,67 @@ void updateAppStateForEmptyFeedback() {
});
}

// Build log parameters for structured memory processing
Map<String, dynamic> buildLogParameters(ApiCallResponse response) {
return {
'jsonBody': (response.jsonBody ?? ''),
'memory': FFAppState().lastMemory,
'user': currentUserReference,
};
}

// Finalize memory record after processing feedback
Future<void> finalizeMemoryRecord(ApiCallResponse structuredMemoryResponse) async {
var vectorResponse = await vectorizeMemory(structuredMemoryResponse);
Future<void> finalizeMemoryRecord(String structuredMemory) async {
var vector = await vectorizeMemory(structuredMemory);
logFirebaseEvent('memoryCreationBlock_backend_call');
var memoryRecord = await createMemoryRecord(structuredMemoryResponse, vectorResponse);
var memoryRecord = await createMemoryRecord(structuredMemory, vector);
logFirebaseEvent('memoryCreationBlock_backend_call');
await storeVectorData(memoryRecord, vectorResponse);
await storeVectorData(memoryRecord, vector);
}

// Call vectorization API for structured memory
Future<ApiCallResponse> vectorizeMemory(ApiCallResponse structuredMemoryResponse) async {
// debugPrint('vectorizeMemory ${structuredMemoryResponse.jsonBody}');
var input = StructuredMemoryCall.responsegpt(
(structuredMemoryResponse.jsonBody ?? ''),
);
return await VectorizeCall.call(input: input?.toString());
Future<List<double>> vectorizeMemory(String structuredMemory) async {
return await getEmbeddingsFromInput(structuredMemory);
}

// Create memory record
Future<MemoriesRecord> createMemoryRecord(
ApiCallResponse structuredMemoryResponse, ApiCallResponse vectorResponse) async {
Future<MemoriesRecord> createMemoryRecord(String structuredMemory, List<double> vector) async {
var recordRef = MemoriesRecord.collection.doc();
await recordRef.set({
...createMemoriesRecordData(
memory: FFAppState().lastMemory,
user: currentUserReference,
structuredMemory: extractContent(structuredMemoryResponse),
structuredMemory: structuredMemory,
feedback: FFAppState().feedback,
toShowToUserShowHide: FFAppState().isFeedbackUseful,
emptyMemory: FFAppState().lastMemory == '',
isUselessMemory: functions.memoryContainsNA(extractContent(structuredMemoryResponse)),
isUselessMemory: functions.memoryContainsNA(structuredMemory),
),
...mapToFirestore({
'date': FieldValue.serverTimestamp(),
'vector': VectorizeCall.embedding((vectorResponse.jsonBody ?? '')),
'vector': vector,
}),
});
return MemoriesRecord.getDocumentFromData({
...createMemoriesRecordData(
memory: FFAppState().lastMemory,
user: currentUserReference,
structuredMemory: extractContent(structuredMemoryResponse),
structuredMemory: structuredMemory,
feedback: FFAppState().feedback,
toShowToUserShowHide: FFAppState().isFeedbackUseful,
emptyMemory: FFAppState().lastMemory == '',
isUselessMemory: functions.memoryContainsNA(extractContent(structuredMemoryResponse)),
isUselessMemory: functions.memoryContainsNA(structuredMemory),
),
...mapToFirestore({
'date': DateTime.now(),
'vector': VectorizeCall.embedding((vectorResponse.jsonBody ?? '')),
'vector': vector,
}),
}, recordRef);
}

// Store vector data after memory record creation
Future<void> storeVectorData(MemoriesRecord memoryRecord, ApiCallResponse vectorResponse) async {
Future<void> storeVectorData(MemoriesRecord memoryRecord, List<double> vector) async {
// debugPrint('storeVectorData: memoryRecord -> $memoryRecord');
// debugPrint('storeVectorData: vectorResponse -> ${vectorResponse.jsonBody}');

var vectorAdded = await CreateVectorPineconeCall.call(
vectorList: VectorizeCall.embedding((vectorResponse.jsonBody ?? '')),
id: memoryRecord.reference.id,
structuredMemory: memoryRecord.structuredMemory,
await createPineconeVector(
vector,
memoryRecord.structuredMemory,
memoryRecord.reference.id,
);
// debugPrint('storeVectorData VectorAdded: ${vectorAdded.statusCode} ${vectorAdded.jsonBody}');
// TODO: this is never triggering as `toShowToUserShowHide` is set to feedback
if (memoryRecord.toShowToUserShowHide == 'Show' && !memoryRecord.emptyMemory && !memoryRecord.isUselessMemory) {
logFirebaseEvent('memoryCreationBlock_trigger_push_notific');
if (currentUserReference != null) {
Expand Down Expand Up @@ -243,31 +223,27 @@ Future<void> processVoiceCommand(List<MemoriesRecord> memories) async {
FFAppState().update(() {
FFAppState().commandState = 'Thinking...';
});

var result = await VoiceCommandRespondCall.call(
memory: functions.limitTranscript(FFAppState().stt, 12000),
longTermMemory: functions.jsonEncodeString(functions.documentsToText(memories.toList())),
);

updateAppStateForVoiceResult(result);
if (result.succeeded ?? true) {
var result = await voiceCommandRequest(functions.limitTranscript(FFAppState().stt, 12000),
functions.jsonEncodeString(functions.documentsToText(memories.toList())));
updateAppStateForVoiceResult();
if (result != '') {
triggerVoiceCommandNotification(result);
await saveVoiceCommandMemory(result);
}
}

// Update app state after voice command results are processed
void updateAppStateForVoiceResult(ApiCallResponse result) {
void updateAppStateForVoiceResult() {
FFAppState().commandState = 'Query';
}

// Trigger notifications based on voice command results
void triggerVoiceCommandNotification(ApiCallResponse result) {
void triggerVoiceCommandNotification(String result) {
logFirebaseEvent('voiceCommandBlock_trigger_push_notification');
if (currentUserReference != null) {
triggerPushNotification(
notificationTitle: 'Sama',
notificationText: extractContent(result),
notificationText: result,
notificationSound: 'default',
userRefs: [currentUserReference!],
initialPageName: 'chat',
Expand All @@ -277,11 +253,11 @@ void triggerVoiceCommandNotification(ApiCallResponse result) {
}

// Save the memory from a voice command
Future<void> saveVoiceCommandMemory(ApiCallResponse result) async {
Future<void> saveVoiceCommandMemory(String result) async {
await MemoriesRecord.collection.doc().set({
...createMemoriesRecordData(
user: currentUserReference,
feedback: extractContent(result),
feedback: result,
toShowToUserShowHide: 'Show',
emptyMemory: true,
isUselessMemory: false,
Expand Down Expand Up @@ -312,7 +288,7 @@ void updateLastMemory(String lastWords) {
Future<void> onFinishAction(BuildContext context) async {
String lastWordsOnFinishAction = await actions.getLastWords();
logFirebaseEvent('OnFinishAction_custom_action');
await actions.debugLog('LAST WORDS FINISH: $lastWordsOnFinishAction');
debugPrint('LAST WORDS FINISH: $lastWordsOnFinishAction');

updateMemoryOnFinish(lastWordsOnFinishAction);
logFirebaseEvent('OnFinishAction_action_block');
Expand Down

0 comments on commit 630ee59

Please sign in to comment.