v1.0.13 openai chat completion

This commit is contained in:
Tibor Bossanyi 2023-03-12 21:48:03 +01:00
parent f34a57e931
commit bed94e572e
7 changed files with 153 additions and 32 deletions

View File

@ -1,43 +1,46 @@
Workout Test and Diet 4 You Common Util Functions Workout Test and Diet 4 You Common Util Functions
Version 1.0.13
OpenAI chat completion extension
Version 1.0.12 Version 1.0.12
CustomerProperty and CustomerMembership fromJson CustomerProperty and CustomerMembership fromJson
Version 1.0.11 Version 1.0.11
No FCM on Web No FCM on Web
Version 1.0.11 Version 1.0.11
Sentry and logging only in debugMode Sentry and logging only in debugMode
Version 1.0.10 Version 1.0.10
Firebase FCM for web Firebase FCM for web
Version 1.0.9 Version 1.0.9
Firebase web config Firebase web config
Version 1.0.8 Version 1.0.8
mombership model error fix mombership model error fix
Version 1.0.7 Version 1.0.7
openai with model name and temperature openai with model name and temperature
Version 1.0.6 Version 1.0.6
membership, customer_membership membership, customer_membership
Version 1.0.5 Version 1.0.5
number picker widget number picker widget
Version 1.0.4 Version 1.0.4
webapi client fixes webapi client fixes
Version 1.0.3 Version 1.0.3
Warning fixes, webapi client Warning fixes, webapi client
Version 1.0.2 Version 1.0.2
Open AI API support Open AI API support
Version 1.0.1 Version 1.0.1
changes from aitrainer_app 1.1.29 working copy changes from aitrainer_app 1.1.29 working copy
Version 1.0.0 Version 1.0.0
outsourced from aitrainer_app 1.1.28 outsourced from aitrainer_app 1.1.28

View File

@ -119,6 +119,8 @@ class Cache with Logging {
static String baseUrlLive = 'https://api.workouttest.org/api/'; static String baseUrlLive = 'https://api.workouttest.org/api/';
static String baseUrlTest = 'https://apitest.workouttest.org/api/'; static String baseUrlTest = 'https://apitest.workouttest.org/api/';
static String baseUrlDiet = 'https://api.diet4you.eu/api/';
static String baseUrlDietTest = 'https://apitest.diet4you.eu/api/';
static String baseUrlLocal = 'http://localhost:8443/api/'; static String baseUrlLocal = 'http://localhost:8443/api/';
late String baseUrl; late String baseUrl;
static const String mediaUrl = 'https://admin.workouttest.org/media/'; static const String mediaUrl = 'https://admin.workouttest.org/media/';
@ -200,7 +202,7 @@ class Cache with Logging {
if (testEnv == "1") { if (testEnv == "1") {
baseUrl = baseUrlTest; baseUrl = baseUrlTest;
liveServer = false; liveServer = false;
} else if ( testEnv == "2") { } else if (testEnv == "2") {
baseUrl = baseUrlLocal; baseUrl = baseUrlLocal;
liveServer = false; liveServer = false;
} }
@ -214,6 +216,14 @@ class Cache with Logging {
baseUrl = baseUrlTest; baseUrl = baseUrlTest;
} }
void setDietTestBaseUrl() {
baseUrl = baseUrlDietTest;
}
void setDietBaseUrl() {
baseUrl = baseUrlDiet;
}
void setLocalBaseUrl() { void setLocalBaseUrl() {
baseUrl = baseUrlLocal; baseUrl = baseUrlLocal;
} }
@ -374,7 +384,7 @@ class Cache with Logging {
baseUrl = baseUrlTest; baseUrl = baseUrlTest;
log("TestEnv $baseUrl"); log("TestEnv $baseUrl");
return; return;
} else if ( testEnvironment == "2") { } else if (testEnvironment == "2") {
baseUrl = baseUrlLocal; baseUrl = baseUrlLocal;
log("TestEnv $baseUrl"); log("TestEnv $baseUrl");
return; return;
@ -563,8 +573,7 @@ class Cache with Logging {
ExercisePlan? getMyExercisePlan() => _myExercisePlan; ExercisePlan? getMyExercisePlan() => _myExercisePlan;
void setMyExercisePlanDetails(LinkedHashMap<int, ExercisePlanDetail> listExercisePlanDetail) => void setMyExercisePlanDetails(LinkedHashMap<int, ExercisePlanDetail> listExercisePlanDetail) => _myExercisesPlanDetails = listExercisePlanDetail;
_myExercisesPlanDetails = listExercisePlanDetail;
void addToMyExercisePlanDetails(ExercisePlanDetail detail) => _myExercisesPlanDetails[detail.exerciseTypeId] = detail; void addToMyExercisePlanDetails(ExercisePlanDetail detail) => _myExercisesPlanDetails[detail.exerciseTypeId] = detail;
@ -578,8 +587,7 @@ class Cache with Logging {
void deleteMyExercisePlanDetail(ExercisePlanDetail detail) => deleteMyExercisePlanDetailByExerciseTypeId(detail.exerciseTypeId); void deleteMyExercisePlanDetail(ExercisePlanDetail detail) => deleteMyExercisePlanDetailByExerciseTypeId(detail.exerciseTypeId);
void deletedMyExercisePlanDetail(ExercisePlanDetail detail) => void deletedMyExercisePlanDetail(ExercisePlanDetail detail) => _myExercisesPlanDetails[detail.exerciseTypeId]!.change = ModelChange.deleted;
_myExercisesPlanDetails[detail.exerciseTypeId]!.change = ModelChange.deleted;
void deleteMyExercisePlanDetailByExerciseTypeId(int exerciseTypeId) { void deleteMyExercisePlanDetailByExerciseTypeId(int exerciseTypeId) {
_myExercisesPlanDetails[exerciseTypeId]!.change = ModelChange.delete; _myExercisesPlanDetails[exerciseTypeId]!.change = ModelChange.delete;

View File

@ -0,0 +1,25 @@
class OpenAIChat {
int id = 0;
late String messages; // JSON of ChatMessage
String modelName = "gpt-3.5-turbo";
double temperature = 0.1;
OpenAIChat(this.messages, {String? modelName, double? temperature});
OpenAIChat.fromJson(Map json) {
id = json["id"];
messages = json['messages'];
modelName = json['modelName'];
temperature = json['temperature'];
}
Map<String, dynamic> toJson() => {
"id": id,
"messages": messages,
"modelName": modelName,
"temperature": temperature,
};
@override
String toString() => toJson().toString();
}

View File

@ -0,0 +1,41 @@
enum ChatRole { user, assistant, system }
extension ChatRoleExt on ChatRole {
String enumToStr() => toString().split(".").last;
bool equalsTo(ChatRole role) => toString() == role.toString();
bool equalsStringTo(String role) => enumToStr() == role;
}
class OpenAIChatMessage {
late ChatRole role; // JSON of ChatMessage
late String content;
String? name;
OpenAIChatMessage(this.role, this.content, {String? name});
OpenAIChatMessage.fromJson(Map json) {
role = toChatRole(json['role']);
content = json['content'];
name = json['name'] ?? "";
}
ChatRole toChatRole(String strRole) {
ChatRole role = ChatRole.user;
for (ChatRole chatRole in ChatRole.values) {
if (chatRole.equalsStringTo(strRole)) {
role = chatRole;
break;
}
}
return role;
}
Map<String, dynamic> toJson() => {
"role": role.enumToStr(),
"content": content,
"name": name,
};
@override
String toString() => toJson().toString();
}

View File

@ -2,10 +2,10 @@ import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:workouttest_util/model/openai.dart'; import 'package:workouttest_util/model/openai.dart';
import 'package:workouttest_util/model/openai_chat.dart';
import 'package:workouttest_util/service/api.dart'; import 'package:workouttest_util/service/api.dart';
import 'package:workouttest_util/util/logging.dart'; import 'package:workouttest_util/util/logging.dart';
class OpenAIApi with Logging { class OpenAIApi with Logging {
final APIClient _client = APIClient(); final APIClient _client = APIClient();
@ -34,4 +34,17 @@ class OpenAIApi with Logging {
} }
return response ?? ""; return response ?? "";
} }
Future<String> getOpenAIChatCompletion(OpenAIChat openai) async {
String? response;
try {
String body = const JsonEncoder().convert(openai.toJson());
response = await _client.post("openai/chat_completion", body);
} on TimeoutException catch (_) {
log("Timeout from OpenAI");
} on Exception catch (e) {
log(e.toString());
}
return response ?? "";
}
} }

View File

@ -1,6 +1,6 @@
name: workouttest_util name: workouttest_util
description: Workout Test app and web functions. description: Workout Test app and web functions.
version: 1.0.12 version: 1.0.13
environment: environment:
sdk: ">=2.18.6 <3.0.0" sdk: ">=2.18.6 <3.0.0"

View File

@ -1,8 +1,10 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:workouttest_util/model/cache.dart'; import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/openai.dart'; import 'package:workouttest_util/model/openai.dart';
import 'package:workouttest_util/model/openai_chat.dart';
import 'package:workouttest_util/model/openai_chat_message.dart';
import 'package:workouttest_util/service/openai_service.dart'; import 'package:workouttest_util/service/openai_service.dart';
import 'dart:convert';
void main() { void main() {
setUp(() { setUp(() {
@ -13,15 +15,44 @@ void main() {
var api = OpenAIApi(); var api = OpenAIApi();
String response = await api.getOpenAICompletion("Who wrote the song 'yellow submarine'?"); String response = await api.getOpenAICompletion("Who wrote the song 'yellow submarine'?");
print(response); print(response);
expect(response, matches(RegExp(r'Beatles') )); expect(response, matches(RegExp(r'Beatles')));
}); });
test('openai with model response succesful', () async { test('openai with model response succesful', () async {
var api = OpenAIApi(); var api = OpenAIApi();
String question = "Készíts egy heti egészséges és változatos étrendet egy új felhasználónak az alábbi adatok alapján: férfi, 51 éves. Célja: Le szeretnék fogyni, heti mozgás: Hetente 3-4 alkalom, BMI: 24.784257517393772, BMR: 1723.75. A neve Tibi. Az egyes étkezések különbözőek legyenek, és add meg hozzájuk a mennyiséget és a kalóriatartalmat is. Vedd figyelembe, hogy a napi összes kalóriaérték 200-400 kCal-val kevesebb legyen, mint 1723.75 kCal"; String question =
"Készíts egy heti egészséges és változatos étrendet egy új felhasználónak az alábbi adatok alapján: férfi, 51 éves. Célja: Le szeretnék fogyni, heti mozgás: Hetente 3-4 alkalom, BMI: 24.784257517393772, BMR: 1723.75. A neve Tibi. Az egyes étkezések különbözőek legyenek, és add meg hozzájuk a mennyiséget és a kalóriatartalmat is. Vedd figyelembe, hogy a napi összes kalóriaérték 200-400 kCal-val kevesebb legyen, mint 1723.75 kCal";
var openai = OpenAI(question, "text-davinci-003", 0.5); var openai = OpenAI(question, "text-davinci-003", 0.5);
String response = await api.getOpenAICompletionWithModel(openai); String response = await api.getOpenAICompletionWithModel(openai);
print(response); print(response);
expect(response, matches(RegExp(r'Tibi') )); expect(response, matches(RegExp(r'Tibi')));
});
test('openai chat completion response succesful', () async {
var api = OpenAIApi();
String content =
"Te a Diet4You applikáció asszisztense vagy. Add meg ennek az ételnek a kalória és tápanyagadatait: 'Hortobágyi palacsinta'. A válasz ez az objektum JSON alakított formája legyen: Meal [mealName: string, cal: double, ch: double, fat: double, protein: double, sugar: double, portion: double, unit: string]. A portion paraméter azt tartalmazza, hogy ebből az ételből hány gramm v. ml az átlagos adag. A unit paraméter a 'portion' mennyiségi egyésge";
OpenAIChatMessage message = OpenAIChatMessage(ChatRole.user, content);
String json = jsonEncode([message]);
var openai = OpenAIChat(json);
String response = await api.getOpenAIChatCompletion(openai);
print(response);
expect(response, matches(RegExp(r'mealName')));
});
test('openai chat completion response succesful 2', () async {
var api = OpenAIApi();
String content =
"Te a Diet4You applikáció asszisztense vagy. Add meg ennek az ételnek a kalória és tápanyagadatait: 'Szegedi halászlé'. A válasz ez az objektum JSON alakított formája legyen: Meal [mealName: string, cal: double, ch: double, fat: double, protein: double, sugar: double, portion: double, unit: string]. A portion paraméter azt tartalmazza, hogy ebből az ételből hány gramm v. ml az átlagos adag. A unit paraméter a 'portion' mennyiségi egyésge";
OpenAIChatMessage message = OpenAIChatMessage(ChatRole.user, content);
String json = jsonEncode([message]);
var openai = OpenAIChat(json);
String response = await api.getOpenAIChatCompletion(openai);
print(response);
expect(response, matches(RegExp(r'mealName')));
}); });
} }