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
Version 1.0.13
OpenAI chat completion extension
Version 1.0.12
CustomerProperty and CustomerMembership fromJson
CustomerProperty and CustomerMembership fromJson
Version 1.0.11
No FCM on Web
No FCM on Web
Version 1.0.11
Sentry and logging only in debugMode
Sentry and logging only in debugMode
Version 1.0.10
Firebase FCM for web
Firebase FCM for web
Version 1.0.9
Firebase web config
Firebase web config
Version 1.0.8
mombership model error fix
mombership model error fix
Version 1.0.7
openai with model name and temperature
openai with model name and temperature
Version 1.0.6
membership, customer_membership
membership, customer_membership
Version 1.0.5
number picker widget
number picker widget
Version 1.0.4
webapi client fixes
webapi client fixes
Version 1.0.3
Warning fixes, webapi client
Warning fixes, webapi client
Version 1.0.2
Open AI API support
Open AI API support
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
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 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/';
late String baseUrl;
static const String mediaUrl = 'https://admin.workouttest.org/media/';
@ -200,7 +202,7 @@ class Cache with Logging {
if (testEnv == "1") {
baseUrl = baseUrlTest;
liveServer = false;
} else if ( testEnv == "2") {
} else if (testEnv == "2") {
baseUrl = baseUrlLocal;
liveServer = false;
}
@ -214,6 +216,14 @@ class Cache with Logging {
baseUrl = baseUrlTest;
}
void setDietTestBaseUrl() {
baseUrl = baseUrlDietTest;
}
void setDietBaseUrl() {
baseUrl = baseUrlDiet;
}
void setLocalBaseUrl() {
baseUrl = baseUrlLocal;
}
@ -374,7 +384,7 @@ class Cache with Logging {
baseUrl = baseUrlTest;
log("TestEnv $baseUrl");
return;
} else if ( testEnvironment == "2") {
} else if (testEnvironment == "2") {
baseUrl = baseUrlLocal;
log("TestEnv $baseUrl");
return;
@ -563,8 +573,7 @@ class Cache with Logging {
ExercisePlan? getMyExercisePlan() => _myExercisePlan;
void setMyExercisePlanDetails(LinkedHashMap<int, ExercisePlanDetail> listExercisePlanDetail) =>
_myExercisesPlanDetails = listExercisePlanDetail;
void setMyExercisePlanDetails(LinkedHashMap<int, ExercisePlanDetail> listExercisePlanDetail) => _myExercisesPlanDetails = listExercisePlanDetail;
void addToMyExercisePlanDetails(ExercisePlanDetail detail) => _myExercisesPlanDetails[detail.exerciseTypeId] = detail;
@ -578,8 +587,7 @@ class Cache with Logging {
void deleteMyExercisePlanDetail(ExercisePlanDetail detail) => deleteMyExercisePlanDetailByExerciseTypeId(detail.exerciseTypeId);
void deletedMyExercisePlanDetail(ExercisePlanDetail detail) =>
_myExercisesPlanDetails[detail.exerciseTypeId]!.change = ModelChange.deleted;
void deletedMyExercisePlanDetail(ExercisePlanDetail detail) => _myExercisesPlanDetails[detail.exerciseTypeId]!.change = ModelChange.deleted;
void deleteMyExercisePlanDetailByExerciseTypeId(int exerciseTypeId) {
_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 '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/util/logging.dart';
class OpenAIApi with Logging {
final APIClient _client = APIClient();
@ -34,4 +34,17 @@ class OpenAIApi with Logging {
}
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
description: Workout Test app and web functions.
version: 1.0.12
version: 1.0.13
environment:
sdk: ">=2.18.6 <3.0.0"

View File

@ -1,8 +1,10 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:workouttest_util/model/cache.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 'dart:convert';
void main() {
setUp(() {
@ -13,15 +15,44 @@ void main() {
var api = OpenAIApi();
String response = await api.getOpenAICompletion("Who wrote the song 'yellow submarine'?");
print(response);
expect(response, matches(RegExp(r'Beatles') ));
expect(response, matches(RegExp(r'Beatles')));
});
test('openai with model response succesful', () async {
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);
String response = await api.getOpenAICompletionWithModel(openai);
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')));
});
}