diff --git a/CHANGELOG.md b/CHANGELOG.md index 40c1511..144ffd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -191,4 +191,10 @@ - Fix create transcribes error - Create speech - Embedding - - Add new Model \ No newline at end of file + - Add new Model +- Thread + - Create a thread. + - Retrieves a thread. + - Modifies a thread. + - Delete a thread. + \ No newline at end of file diff --git a/lib/src/model/file/request/upload_file.dart b/lib/src/model/file/request/upload_file.dart index a41a952..857a188 100644 --- a/lib/src/model/file/request/upload_file.dart +++ b/lib/src/model/file/request/upload_file.dart @@ -19,7 +19,7 @@ class UploadFile { Future getForm() async { return FormData.fromMap({ - 'file': File(file.path).existsSync() + 'file': (await File(file.path).exists()) ? await MultipartFile.fromFile(file.path, filename: file.name) : null, 'purpose': purpose, diff --git a/lib/src/model/thread/request/thread_request.dart b/lib/src/model/thread/request/thread_request.dart new file mode 100644 index 0000000..18153cf --- /dev/null +++ b/lib/src/model/thread/request/thread_request.dart @@ -0,0 +1,18 @@ +class ThreadRequest { + final List>? messages; + + ///Set of 16 key-value pairs that can be attached to an object. + /// This can be useful for storing additional information about the + /// object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// [metadata] + final Map? metadata; + + ThreadRequest({this.messages, this.metadata}); + + Map toJson() => Map.of({ + 'messages': messages, + 'metadata': metadata, + }) + ..removeWhere((_, value) => value == null); +} diff --git a/lib/src/model/thread/response/thread_delete_response.dart b/lib/src/model/thread/response/thread_delete_response.dart new file mode 100644 index 0000000..4432706 --- /dev/null +++ b/lib/src/model/thread/response/thread_delete_response.dart @@ -0,0 +1,24 @@ +class ThreadDeleteResponse { + ThreadDeleteResponse({ + required this.deleted, + required this.id, + required this.object, + }); + + bool deleted; + String id; + String object; + + factory ThreadDeleteResponse.fromJson(Map json) => + ThreadDeleteResponse( + deleted: json["deleted"] ?? false, + id: json["id"] ?? '', + object: json["object"] ?? '', + ); + + Map toJson() => { + "deleted": deleted, + "id": id, + "object": object, + }; +} diff --git a/lib/src/model/thread/response/thread_response.dart b/lib/src/model/thread/response/thread_response.dart new file mode 100644 index 0000000..65eb4ce --- /dev/null +++ b/lib/src/model/thread/response/thread_response.dart @@ -0,0 +1,27 @@ +class ThreadResponse { + ThreadResponse({ + required this.metadata, + required this.createdAt, + required this.id, + required this.object, + }); + + Map metadata; + int createdAt; + String id; + String object; + + factory ThreadResponse.fromJson(Map json) => ThreadResponse( + metadata: json["metadata"] ?? {}, + createdAt: json["created_at"] ?? 0, + id: json["id"] ?? '', + object: json["object"] ?? '', + ); + + Map toJson() => { + "metadata": metadata, + "created_at": createdAt, + "id": id, + "object": object, + }; +} diff --git a/lib/src/openai.dart b/lib/src/openai.dart index dc4f161..48afcf4 100644 --- a/lib/src/openai.dart +++ b/lib/src/openai.dart @@ -18,6 +18,7 @@ import 'package:chat_gpt_sdk/src/model/gen_image/response/gen_img_response.dart' import 'package:chat_gpt_sdk/src/model/openai_engine/engine_model.dart'; import 'package:chat_gpt_sdk/src/model/openai_model/openai_model.dart'; import 'package:chat_gpt_sdk/src/moderation.dart'; +import 'package:chat_gpt_sdk/src/threads.dart'; import 'package:chat_gpt_sdk/src/utils/constants.dart'; import 'package:chat_gpt_sdk/src/utils/token_builder.dart'; import 'package:dio/dio.dart'; @@ -232,4 +233,6 @@ class OpenAI implements IOpenAI { ///Assistants Assistants get assistant => Assistants(_client); + + Threads get threads => Threads(client: _client); } diff --git a/lib/src/threads.dart b/lib/src/threads.dart new file mode 100644 index 0000000..efe1d50 --- /dev/null +++ b/lib/src/threads.dart @@ -0,0 +1,70 @@ +import 'package:chat_gpt_sdk/src/client/openai_client.dart'; +import 'package:chat_gpt_sdk/src/model/thread/request/thread_request.dart'; +import 'package:chat_gpt_sdk/src/model/thread/response/thread_delete_response.dart'; +import 'package:chat_gpt_sdk/src/model/thread/response/thread_response.dart'; +import 'package:chat_gpt_sdk/src/utils/constants.dart'; + +class Threads { + final OpenAIClient _client; + + Threads({required OpenAIClient client}) : _client = client; + + Map _headers = {'OpenAI-Beta': 'assistants=v1'}; + Map get getHeader => _headers; + + void addHeader(Map mHeader) { + if (mHeader == {}) return; + + _headers.addAll(mHeader); + } + + ///Create a thread. + /// [createThread] + Future createThread({ + ThreadRequest? request, + }) { + return _client.post( + _client.apiUrl + kThread, + request == null ? {} : request.toJson(), + headers: _headers, + onSuccess: ThreadResponse.fromJson, + onCancel: (cancelData) => null, + ); + } + + ///The ID of the thread to retrieve.[threadId] + /// [retrieveThread] + Future retrieveThread({ + required String threadId, + }) { + return _client.get( + _client.apiUrl + kThread + "/$threadId", + headers: _headers, + onSuccess: ThreadResponse.fromJson, + onCancel: (cancelData) => null, + ); + } + + Future modifyThread({ + required String threadId, + required Map metadata, + }) { + return _client.post( + _client.apiUrl + kThread + "/$threadId", + metadata, + headers: _headers, + onSuccess: ThreadResponse.fromJson, + onCancel: (cancelData) => null, + ); + } + + Future deleteThread({ + required String threadId, + }) { + return _client.delete( + _client.apiUrl + kThread + "/$threadId", + onSuccess: ThreadDeleteResponse.fromJson, + onCancel: (cancelData) => null, + ); + } +} diff --git a/lib/src/utils/constants.dart b/lib/src/utils/constants.dart index 316d590..7584718 100644 --- a/lib/src/utils/constants.dart +++ b/lib/src/utils/constants.dart @@ -39,6 +39,9 @@ const kFile = 'files'; const kFineTune = 'fine-tunes'; const kFineTuneJob = '$kFineTune/jobs'; +///threads +const kThread = 'threads'; + /// fine tune model const kFineTuneModel = 'models';