Skip to content

Commit

Permalink
hugging face
Browse files Browse the repository at this point in the history
  • Loading branch information
Starland9 committed Jul 1, 2023
1 parent 54d010e commit e3ac0b0
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 196 deletions.
1 change: 0 additions & 1 deletion lib/apis/keys/ninja.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
class ApiKeys {
static const ninja = "MqP1o6xY70Aq40AyhCkZ6g==Ydp5zzxo1Zr5qSUB";
static const huggingFace = "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";
}
49 changes: 49 additions & 0 deletions lib/apis/services/hugging_face.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import 'dart:convert';

import 'package:http/http.dart' as http;
import 'package:translator/translator.dart';

import '../../models/recipe/recipe.dart';
import '../keys/ninja.dart';

class HuggingFace {
static final HuggingFace _instance = HuggingFace._internal();

factory HuggingFace() {
return _instance;
}

HuggingFace._internal();

static const modelsUrl = "https://api-inference.huggingface.co/models/";

Uri _getModel(String modelName) {
return Uri.parse(modelsUrl + modelName);
}

Future? getRecipe(List<String> ingredients) async {
try {
String translatedIngredients =
(await ingredients.join(",").translate()).text;

var r = await http.post(
_getModel("flax-community/t5-recipe-generation"),
headers: _getHds,
body: translatedIngredients,
);

return Recipe.from(jsonDecode(r.body)[0]["generated_text"]);
} catch (e) {
print(e);
return "Une erreur est survenue \n$e";
}
}

Map<String, String> get _getHds {
return {
'Authorization': "Bearer ${ApiKeys.huggingFace}",
"Accept": "*/*",
"Content-Type": "application/json",
};
}
}
59 changes: 0 additions & 59 deletions lib/apis/services/ninja.dart

This file was deleted.

2 changes: 1 addition & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class MainApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Recipe Discover",
title: "Recipe Generator",
debugShowCheckedModeBanner: false,
home: const HomePage(),
theme: ThemeData(
Expand Down
53 changes: 27 additions & 26 deletions lib/models/recipe/recipe.dart
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
class Recipe {
String? title;
String? ingredients;
String? servings;
String? instructions;
String title;
String ingredients;
String directions;

Recipe({
this.title,
this.ingredients,
this.servings,
this.instructions,
required this.title,
required this.ingredients,
required this.directions,
});

Map<String, dynamic> toJson() => {
'title': title,
'ingredients': ingredients,
'servings': servings,
'instructions': instructions,
};
factory Recipe.from(String text) {
List<String> results = ["", "", ""];

List<String> words = text.split(" ");
int index = 0;
for (var word in words) {
if (word == "title:") {
index = 0;
} else if (word == "ingredients:") {
index = 1;
} else if (word == "directions:") {
index = 2;
}
if (["title:", "ingredients:", "directions:"].contains(word)) {
continue;
}
results[index] += "$word ";
}

factory Recipe.fromJson(Map<String, dynamic> json) {
return Recipe(
title: json['title'],
ingredients: json['ingredients'],
servings: json['servings'],
instructions: json['instructions'],
title: results[0],
ingredients: results[1],
directions: results[2],
);
}

bool containsIngredient(String word) {
return ingredients!.contains(word) ||
instructions!.contains(word) ||
servings!.contains(word) ||
title!.contains(word);
}
}
9 changes: 5 additions & 4 deletions lib/modules/home/components/buttons.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart';

import '../../../apis/services/ninja.dart';
import 'package:recipe_finder/apis/services/hugging_face.dart';

class FindButton extends StatelessWidget {
const FindButton({
Expand All @@ -16,11 +15,13 @@ class FindButton extends StatelessWidget {
Widget build(BuildContext context) {
return FilledButton.icon(
style: const ButtonStyle(
fixedSize: MaterialStatePropertyAll(Size(double.maxFinite, 50)),
fixedSize: MaterialStatePropertyAll(
Size(double.maxFinite, 50),
),
),
onPressed: () {
onTap!("Nous cherchons ta recette...");
Ninja.getFullRecipes(ingredients)?.then((value) {
HuggingFace().getRecipe(ingredients)?.then((value) {
onTap!(value);
});
},
Expand Down
Empty file.
4 changes: 2 additions & 2 deletions lib/modules/home/components/search.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ class SearchInput extends StatelessWidget {
contentPadding: const EdgeInsets.only(left: 10),
border: OutlineInputBorder(
gapPadding: 0,
borderRadius: BorderRadius.circular(15),
borderRadius: BorderRadius.circular(12),
),
hintText: "Ajoute ton ingredient ici",
suffixIcon: IconButton.filled(
style: const ButtonStyle(
shape: MaterialStatePropertyAll(RoundedRectangleBorder(
borderRadius:
BorderRadius.horizontal(right: Radius.circular(15)))),
BorderRadius.horizontal(right: Radius.circular(12)))),
),
onPressed: () {
onSearch!(controller.text);
Expand Down
72 changes: 18 additions & 54 deletions lib/modules/home/home.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import 'package:flutter/material.dart';
import 'package:recipe_finder/models/recipe/recipe.dart';
import 'package:recipe_finder/modules/recipe/recipe.dart';
import 'package:recipe_finder/widgets/texts.dart';

import '../../utils/logic.dart';
import 'components/buttons.dart';
import 'components/search.dart';

Expand All @@ -17,28 +15,21 @@ class HomePage extends StatefulWidget {

class _HomePageState extends State<HomePage> {
List<String> ingredients = [];
List<Recipe>? recipes;
Recipe? recipe;
String? helperText;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Recipe Generator"),
),
backgroundColor: Colors.orange.shade50,
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 30,
),
const Text(
"Trouve ta recette avec ce que tu as dans ton frigo !",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const Divider(),
SearchInput(
onSearch: (text) {
setState(() {
Expand All @@ -65,15 +56,13 @@ class _HomePageState extends State<HomePage> {
.toList(),
),
Expanded(
child: recipes != null || (recipes ?? []).isNotEmpty
? RecipeList(recipes: recipes ?? [])
: Center(
child: Text(
helperText ?? "",
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
child: recipe == null
? Center(child: Text(helperText ?? ""))
: SingleChildScrollView(
child: RecipeCard(
title: recipe!.title,
ingredients: recipe!.ingredients,
instructions: recipe!.directions,
),
),
),
Expand All @@ -89,11 +78,11 @@ class _HomePageState extends State<HomePage> {
}

void _searchRecipe(value) {
helperText == null;
recipes = null;
if (value is List<Recipe>) {
helperText == "Nous concevons une belle recette...";
recipe = null;
if (value is Recipe) {
setState(() {
recipes = value;
recipe = value;
});
}
if (value is String) {
Expand All @@ -103,34 +92,9 @@ class _HomePageState extends State<HomePage> {
}
if (value == null) {
setState(() {
helperText = "Voire les recettes trouvées !";
helperText =
"Le cuisinier est occupé, veuillez patientez et réessayer dans une minute !";
});
}
}
}

class RecipeList extends StatelessWidget {
const RecipeList({super.key, required this.recipes});

final List<Recipe> recipes;

@override
Widget build(BuildContext context) {
return ListView.separated(
itemBuilder: (context, index) {
return ListTile(
leading: const Icon(Icons.food_bank_outlined),
onTap: () {
Nav.push(context, RecipePage(recipe: recipes[index]));
},
title: TextTr(
recipes[index].title!,
),
);
},
separatorBuilder: (context, index) {
return const Divider();
},
itemCount: recipes.length);
}
}
Loading

0 comments on commit e3ac0b0

Please sign in to comment.