diff --git a/README.md b/README.md
index 0cb35a1..12d0f5e 100644
--- a/README.md
+++ b/README.md
@@ -5,14 +5,15 @@
# YChat
-YChat is a Kotlin Multiplatform (KMP) project that provides a simple API for integrating the powerful ChatGPT language model developed by OpenAI into mobile applications running on both iOS and Android. The goal of this project is to abstract all the API call logic from ChatGPT, allowing developers to easily leverage the capabilities of the language model in their mobile applications.
+YChat is a Kotlin Multiplatform (KMP) project that provides a simple API for integrating the powerful ChatGPT language model developed by OpenAI into mobile applications running on multi platforms. The goal of this project is to abstract all the API call logic from ChatGPT, allowing developers to easily leverage the capabilities of the language model in their mobile applications.
The repository contains the source code for the YChat library, along with examples and documentation for getting started with the library. The YChat library provides a consistent interface for interacting with ChatGPT, regardless of the platform, and makes it easy to generate human-like text based on a given prompt or context.
-The library uses Kotlin Multiplatform to generate artifacts for both iOS and Android, allowing developers to write code once and use it on both platforms. The project is open source and actively maintained, with contributions from the community encouraged. Overall, YChat provides a convenient and powerful way for mobile developers to incorporate the advanced natural language processing capabilities of ChatGPT into their applications.
+The library uses Kotlin Multiplatform to generate artifacts for both iOS, Android and JVM, allowing developers to write code once and use it on multiple platforms. The project is open source and actively maintained, with contributions from the community encouraged. Overall, YChat provides a convenient and powerful way for mobile developers to incorporate the advanced natural language processing capabilities of ChatGPT into their applications.
+## ⚡️ Getting Started
-## iOS setup
+### iOS setup
- Go to your project’s file settings and click "Add Package":
@@ -24,7 +25,7 @@ The library uses Kotlin Multiplatform to generate artifacts for both iOS and And
Once you have found the package click the "Add Package" button to add it to your project. Now you can start using the SDK in your iOS project!
-See the code snippet below on how to initialize and use it:
+See the code snippet below on how to initialize and use it one of the supported feature:
```swift
var yChat: YChat {
@@ -43,7 +44,7 @@ do {
}
```
-## Android setup
+### Android/JVM setup
Add the following line to import the library via Gradle. First, make sure Maven Central has been added:
@@ -55,13 +56,13 @@ repositories {
}
```
-Then, simply import the dependency to your common source-set dependencies:
+Then, simply import the dependency to your `build.gradle` dependencies:
```kotlin
-implementation("co.yml:ychat:1.0.0")
+implementation("co.yml:ychat:1.1.0")
```
-In the snippet below, you can see how to initialize the object and perform a first search:
+Take a look at the Kotlin code snippet below for an example of how to initialize and use one of the supported features:
```kotlin
@@ -82,11 +83,28 @@ try {
}
```
+### Features
+
+- [Completions](guides/Features.md#completion)
+- [ChatCompletions](guides/Features.md#chatcompletions)
+- [ImageGenerations](guides/Features.md#imagegenerations)
+- [Edits](guides/Features.md#edits)
+
+## ℹ️ Sample apps
+
+Take a look at our sample apps to learn how to use the SDK on different platforms:
+
+[Android Sample](https://github.com/yml-org/ychat/tree/main/sample/android)
+
+[iOS Sample](https://github.com/yml-org/ychat/tree/main/sample/ios)
+
+[JVM Sample](https://github.com/yml-org/ychat/tree/main/sample/jvm)
+
## 🤝 Contributions
Feel free to make a suggestion or if you find any error in this project, please open an issue. Make sure to read our [contribution guidelines](https://github.com/yml-org/ychat/blob/main/CONTRIBUTING.md) before.
-## License
+## 📄 License
```
Copyright 2023 YML
diff --git a/YChat-1.0.0.zip b/YChat-1.0.0.zip
deleted file mode 100644
index 762bb8d..0000000
Binary files a/YChat-1.0.0.zip and /dev/null differ
diff --git a/YChat-1.1.0.zip b/YChat-1.1.0.zip
new file mode 100644
index 0000000..01c898c
Binary files /dev/null and b/YChat-1.1.0.zip differ
diff --git a/YChat.xcframework/Info.plist b/YChat.xcframework/Info.plist
index 92b884f..b1ef1ce 100644
--- a/YChat.xcframework/Info.plist
+++ b/YChat.xcframework/Info.plist
@@ -5,6 +5,8 @@
AvailableLibraries
+ DebugSymbolsPath
+ dSYMs
LibraryIdentifier
ios-arm64
LibraryPath
@@ -17,6 +19,8 @@
ios
+ DebugSymbolsPath
+ dSYMs
LibraryIdentifier
ios-x86_64-simulator
LibraryPath
diff --git a/YChat.xcframework/ios-arm64/YChat.framework/Headers/YChat.h b/YChat.xcframework/ios-arm64/YChat.framework/Headers/YChat.h
index eb33503..dd8fd13 100644
--- a/YChat.xcframework/ios-arm64/YChat.framework/Headers/YChat.h
+++ b/YChat.xcframework/ios-arm64/YChat.framework/Headers/YChat.h
@@ -6,9 +6,9 @@
#import
#import
-@class YChatKotlinThrowable, YChatYChatCompanion, YChatKotlinArray, YChatKotlinException, YChatKotlinRuntimeException, YChatKotlinIllegalStateException;
+@class YChatKotlinThrowable, YChatYChatCompanion, YChatChatMessage, YChatKotlinArray, YChatKotlinException, YChatKotlinRuntimeException, YChatKotlinIllegalStateException;
-@protocol YChatCompletion, YChatYChat, YChatYChatCallback, YChatKotlinIterator;
+@protocol YChatChatCompletions, YChatCompletion, YChatEdits, YChatImageGenerations, YChatYChat, YChatYChatCallback, YChatKotlinIterator;
NS_ASSUME_NONNULL_BEGIN
#pragma clang diagnostic push
@@ -147,7 +147,10 @@ __attribute__((swift_name("KotlinBoolean")))
__attribute__((swift_name("YChat")))
@protocol YChatYChat
@required
+- (id)chatCompletions __attribute__((swift_name("chatCompletions()")));
- (id)completion __attribute__((swift_name("completion()")));
+- (id)edits __attribute__((swift_name("edits()")));
+- (id)imageGenerations __attribute__((swift_name("imageGenerations()")));
@end
__attribute__((swift_name("YChatCallback")))
@@ -172,6 +175,20 @@ __attribute__((swift_name("YChatCompanion")))
- (id)createApiKey:(NSString *)apiKey __attribute__((swift_name("create(apiKey:)")));
@end
+__attribute__((objc_subclassing_restricted))
+__attribute__((swift_name("ChatMessage")))
+@interface YChatChatMessage : YChatBase
+- (instancetype)initWithRole:(NSString *)role content:(NSString *)content __attribute__((swift_name("init(role:content:)"))) __attribute__((objc_designated_initializer));
+- (NSString *)component1 __attribute__((swift_name("component1()"))) __attribute__((deprecated("use corresponding property instead")));
+- (NSString *)component2 __attribute__((swift_name("component2()"))) __attribute__((deprecated("use corresponding property instead")));
+- (YChatChatMessage *)doCopyRole:(NSString *)role content:(NSString *)content __attribute__((swift_name("doCopy(role:content:)")));
+- (BOOL)isEqual:(id _Nullable)other __attribute__((swift_name("isEqual(_:)")));
+- (NSUInteger)hash __attribute__((swift_name("hash()")));
+- (NSString *)description __attribute__((swift_name("description()")));
+@property (readonly) NSString *content __attribute__((swift_name("content")));
+@property (readonly) NSString *role __attribute__((swift_name("role")));
+@end
+
__attribute__((swift_name("KotlinThrowable")))
@interface YChatKotlinThrowable : YChatBase
- (instancetype)initWithMessage:(NSString * _Nullable)message __attribute__((swift_name("init(message:)"))) __attribute__((objc_designated_initializer));
@@ -209,6 +226,24 @@ __attribute__((swift_name("ChatGptException")))
@property YChatInt * _Nullable statusCode __attribute__((swift_name("statusCode")));
@end
+__attribute__((swift_name("ChatCompletions")))
+@protocol YChatChatCompletions
+@required
+- (id)addMessageRole:(NSString *)role content:(NSString *)content __attribute__((swift_name("addMessage(role:content:)")));
+
+/**
+ * @note This method converts instances of CancellationException, ChatGptException to errors.
+ * Other uncaught Kotlin exceptions are fatal.
+*/
+- (void)executeContent:(NSString *)content completionHandler:(void (^)(NSArray * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("execute(content:completionHandler:)")));
+- (void)executeContent:(NSString *)content callback:(id)callback __attribute__((swift_name("execute(content:callback:)")));
+- (id)setMaxResultsResults:(int32_t)results __attribute__((swift_name("setMaxResults(results:)")));
+- (id)setMaxTokensTokens:(int32_t)tokens __attribute__((swift_name("setMaxTokens(tokens:)")));
+- (id)setModelModel:(NSString *)model __attribute__((swift_name("setModel(model:)")));
+- (id)setTemperatureTemperature:(double)temperature __attribute__((swift_name("setTemperature(temperature:)")));
+- (id)setTopPTopP:(double)topP __attribute__((swift_name("setTopP(topP:)")));
+@end
+
__attribute__((swift_name("Completion")))
@protocol YChatCompletion
@required
@@ -227,6 +262,38 @@ __attribute__((swift_name("Completion")))
- (id)setTopPTopP:(double)topP __attribute__((swift_name("setTopP(topP:)")));
@end
+__attribute__((swift_name("Edits")))
+@protocol YChatEdits
+@required
+
+/**
+ * @note This method converts instances of CancellationException, ChatGptException to errors.
+ * Other uncaught Kotlin exceptions are fatal.
+*/
+- (void)executeInstruction:(NSString *)instruction completionHandler:(void (^)(NSArray * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("execute(instruction:completionHandler:)")));
+- (void)executeInstruction:(NSString *)instruction callback:(id)callback __attribute__((swift_name("execute(instruction:callback:)")));
+- (id)setInputInput:(NSString *)input __attribute__((swift_name("setInput(input:)")));
+- (id)setModelModel:(NSString *)model __attribute__((swift_name("setModel(model:)")));
+- (id)setResultsResults:(int32_t)results __attribute__((swift_name("setResults(results:)")));
+- (id)setTemperatureTemperature:(double)temperature __attribute__((swift_name("setTemperature(temperature:)")));
+- (id)setTopPTopP:(double)topP __attribute__((swift_name("setTopP(topP:)")));
+@end
+
+__attribute__((swift_name("ImageGenerations")))
+@protocol YChatImageGenerations
+@required
+
+/**
+ * @note This method converts instances of CancellationException, ChatGptException to errors.
+ * Other uncaught Kotlin exceptions are fatal.
+*/
+- (void)executePrompt:(NSString *)prompt completionHandler:(void (^)(NSArray * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("execute(prompt:completionHandler:)")));
+- (void)executePrompt:(NSString *)prompt callback:(id)callback __attribute__((swift_name("execute(prompt:callback:)")));
+- (id)setResponseFormatResponseFormat:(NSString *)responseFormat __attribute__((swift_name("setResponseFormat(responseFormat:)")));
+- (id)setResultsResults:(int32_t)results __attribute__((swift_name("setResults(results:)")));
+- (id)setSizeSize:(NSString *)size __attribute__((swift_name("setSize(size:)")));
+@end
+
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("KotlinArray")))
@interface YChatKotlinArray : YChatBase
diff --git a/YChat.xcframework/ios-arm64/YChat.framework/YChat b/YChat.xcframework/ios-arm64/YChat.framework/YChat
index 7492a69..0992ffd 100755
Binary files a/YChat.xcframework/ios-arm64/YChat.framework/YChat and b/YChat.xcframework/ios-arm64/YChat.framework/YChat differ
diff --git a/YChat.xcframework/ios-arm64/dSYMs/YChat.framework.dSYM/Contents/Info.plist b/YChat.xcframework/ios-arm64/dSYMs/YChat.framework.dSYM/Contents/Info.plist
new file mode 100644
index 0000000..fa99c83
--- /dev/null
+++ b/YChat.xcframework/ios-arm64/dSYMs/YChat.framework.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleIdentifier
+ com.apple.xcode.dsym.co.yml.ychat.YChat
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ dSYM
+ CFBundleSignature
+ ????
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+
+
diff --git a/YChat.xcframework/ios-arm64/dSYMs/YChat.framework.dSYM/Contents/Resources/DWARF/YChat b/YChat.xcframework/ios-arm64/dSYMs/YChat.framework.dSYM/Contents/Resources/DWARF/YChat
new file mode 100644
index 0000000..58b1875
Binary files /dev/null and b/YChat.xcframework/ios-arm64/dSYMs/YChat.framework.dSYM/Contents/Resources/DWARF/YChat differ
diff --git a/YChat.xcframework/ios-x86_64-simulator/YChat.framework/Headers/YChat.h b/YChat.xcframework/ios-x86_64-simulator/YChat.framework/Headers/YChat.h
index eb33503..dd8fd13 100644
--- a/YChat.xcframework/ios-x86_64-simulator/YChat.framework/Headers/YChat.h
+++ b/YChat.xcframework/ios-x86_64-simulator/YChat.framework/Headers/YChat.h
@@ -6,9 +6,9 @@
#import
#import
-@class YChatKotlinThrowable, YChatYChatCompanion, YChatKotlinArray, YChatKotlinException, YChatKotlinRuntimeException, YChatKotlinIllegalStateException;
+@class YChatKotlinThrowable, YChatYChatCompanion, YChatChatMessage, YChatKotlinArray, YChatKotlinException, YChatKotlinRuntimeException, YChatKotlinIllegalStateException;
-@protocol YChatCompletion, YChatYChat, YChatYChatCallback, YChatKotlinIterator;
+@protocol YChatChatCompletions, YChatCompletion, YChatEdits, YChatImageGenerations, YChatYChat, YChatYChatCallback, YChatKotlinIterator;
NS_ASSUME_NONNULL_BEGIN
#pragma clang diagnostic push
@@ -147,7 +147,10 @@ __attribute__((swift_name("KotlinBoolean")))
__attribute__((swift_name("YChat")))
@protocol YChatYChat
@required
+- (id)chatCompletions __attribute__((swift_name("chatCompletions()")));
- (id)completion __attribute__((swift_name("completion()")));
+- (id)edits __attribute__((swift_name("edits()")));
+- (id)imageGenerations __attribute__((swift_name("imageGenerations()")));
@end
__attribute__((swift_name("YChatCallback")))
@@ -172,6 +175,20 @@ __attribute__((swift_name("YChatCompanion")))
- (id)createApiKey:(NSString *)apiKey __attribute__((swift_name("create(apiKey:)")));
@end
+__attribute__((objc_subclassing_restricted))
+__attribute__((swift_name("ChatMessage")))
+@interface YChatChatMessage : YChatBase
+- (instancetype)initWithRole:(NSString *)role content:(NSString *)content __attribute__((swift_name("init(role:content:)"))) __attribute__((objc_designated_initializer));
+- (NSString *)component1 __attribute__((swift_name("component1()"))) __attribute__((deprecated("use corresponding property instead")));
+- (NSString *)component2 __attribute__((swift_name("component2()"))) __attribute__((deprecated("use corresponding property instead")));
+- (YChatChatMessage *)doCopyRole:(NSString *)role content:(NSString *)content __attribute__((swift_name("doCopy(role:content:)")));
+- (BOOL)isEqual:(id _Nullable)other __attribute__((swift_name("isEqual(_:)")));
+- (NSUInteger)hash __attribute__((swift_name("hash()")));
+- (NSString *)description __attribute__((swift_name("description()")));
+@property (readonly) NSString *content __attribute__((swift_name("content")));
+@property (readonly) NSString *role __attribute__((swift_name("role")));
+@end
+
__attribute__((swift_name("KotlinThrowable")))
@interface YChatKotlinThrowable : YChatBase
- (instancetype)initWithMessage:(NSString * _Nullable)message __attribute__((swift_name("init(message:)"))) __attribute__((objc_designated_initializer));
@@ -209,6 +226,24 @@ __attribute__((swift_name("ChatGptException")))
@property YChatInt * _Nullable statusCode __attribute__((swift_name("statusCode")));
@end
+__attribute__((swift_name("ChatCompletions")))
+@protocol YChatChatCompletions
+@required
+- (id)addMessageRole:(NSString *)role content:(NSString *)content __attribute__((swift_name("addMessage(role:content:)")));
+
+/**
+ * @note This method converts instances of CancellationException, ChatGptException to errors.
+ * Other uncaught Kotlin exceptions are fatal.
+*/
+- (void)executeContent:(NSString *)content completionHandler:(void (^)(NSArray * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("execute(content:completionHandler:)")));
+- (void)executeContent:(NSString *)content callback:(id)callback __attribute__((swift_name("execute(content:callback:)")));
+- (id)setMaxResultsResults:(int32_t)results __attribute__((swift_name("setMaxResults(results:)")));
+- (id)setMaxTokensTokens:(int32_t)tokens __attribute__((swift_name("setMaxTokens(tokens:)")));
+- (id)setModelModel:(NSString *)model __attribute__((swift_name("setModel(model:)")));
+- (id)setTemperatureTemperature:(double)temperature __attribute__((swift_name("setTemperature(temperature:)")));
+- (id)setTopPTopP:(double)topP __attribute__((swift_name("setTopP(topP:)")));
+@end
+
__attribute__((swift_name("Completion")))
@protocol YChatCompletion
@required
@@ -227,6 +262,38 @@ __attribute__((swift_name("Completion")))
- (id)setTopPTopP:(double)topP __attribute__((swift_name("setTopP(topP:)")));
@end
+__attribute__((swift_name("Edits")))
+@protocol YChatEdits
+@required
+
+/**
+ * @note This method converts instances of CancellationException, ChatGptException to errors.
+ * Other uncaught Kotlin exceptions are fatal.
+*/
+- (void)executeInstruction:(NSString *)instruction completionHandler:(void (^)(NSArray * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("execute(instruction:completionHandler:)")));
+- (void)executeInstruction:(NSString *)instruction callback:(id)callback __attribute__((swift_name("execute(instruction:callback:)")));
+- (id)setInputInput:(NSString *)input __attribute__((swift_name("setInput(input:)")));
+- (id)setModelModel:(NSString *)model __attribute__((swift_name("setModel(model:)")));
+- (id)setResultsResults:(int32_t)results __attribute__((swift_name("setResults(results:)")));
+- (id)setTemperatureTemperature:(double)temperature __attribute__((swift_name("setTemperature(temperature:)")));
+- (id)setTopPTopP:(double)topP __attribute__((swift_name("setTopP(topP:)")));
+@end
+
+__attribute__((swift_name("ImageGenerations")))
+@protocol YChatImageGenerations
+@required
+
+/**
+ * @note This method converts instances of CancellationException, ChatGptException to errors.
+ * Other uncaught Kotlin exceptions are fatal.
+*/
+- (void)executePrompt:(NSString *)prompt completionHandler:(void (^)(NSArray * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("execute(prompt:completionHandler:)")));
+- (void)executePrompt:(NSString *)prompt callback:(id)callback __attribute__((swift_name("execute(prompt:callback:)")));
+- (id)setResponseFormatResponseFormat:(NSString *)responseFormat __attribute__((swift_name("setResponseFormat(responseFormat:)")));
+- (id)setResultsResults:(int32_t)results __attribute__((swift_name("setResults(results:)")));
+- (id)setSizeSize:(NSString *)size __attribute__((swift_name("setSize(size:)")));
+@end
+
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("KotlinArray")))
@interface YChatKotlinArray : YChatBase
diff --git a/YChat.xcframework/ios-x86_64-simulator/YChat.framework/YChat b/YChat.xcframework/ios-x86_64-simulator/YChat.framework/YChat
index 6d7f3ce..82e7d13 100755
Binary files a/YChat.xcframework/ios-x86_64-simulator/YChat.framework/YChat and b/YChat.xcframework/ios-x86_64-simulator/YChat.framework/YChat differ
diff --git a/YChat.xcframework/ios-x86_64-simulator/dSYMs/YChat.framework.dSYM/Contents/Info.plist b/YChat.xcframework/ios-x86_64-simulator/dSYMs/YChat.framework.dSYM/Contents/Info.plist
new file mode 100644
index 0000000..fa99c83
--- /dev/null
+++ b/YChat.xcframework/ios-x86_64-simulator/dSYMs/YChat.framework.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleIdentifier
+ com.apple.xcode.dsym.co.yml.ychat.YChat
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ dSYM
+ CFBundleSignature
+ ????
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+
+
diff --git a/YChat.xcframework/ios-x86_64-simulator/dSYMs/YChat.framework.dSYM/Contents/Resources/DWARF/YChat b/YChat.xcframework/ios-x86_64-simulator/dSYMs/YChat.framework.dSYM/Contents/Resources/DWARF/YChat
new file mode 100644
index 0000000..70230b4
Binary files /dev/null and b/YChat.xcframework/ios-x86_64-simulator/dSYMs/YChat.framework.dSYM/Contents/Resources/DWARF/YChat differ
diff --git a/gradle.properties b/gradle.properties
index 27b9bf1..a17be81 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -11,7 +11,7 @@ kotlin.mpp.enableCInteropCommonization=true
# Lib
GROUP=co.yml
POM_ARTIFACT_ID=ychat
-VERSION_NAME=1.0.0
+VERSION_NAME=1.1.0
IOS_NAME=YChat
# OSS
diff --git a/guides/Features.md b/guides/Features.md
new file mode 100644
index 0000000..d53a9c0
--- /dev/null
+++ b/guides/Features.md
@@ -0,0 +1,176 @@
+# Features
+
+- [Completion](#completion)
+- [ChatCompletions](#chatcompletions)
+- [ImageGenerations](#imagegenerations)
+- [Edits](#edits)
+
+## Completion
+
+The completions api can be used for a wide variety of tasks. You input some text as a prompt, and the model will generate a text completion that attempts to match whatever context or pattern you gave it. For example, if you give the API the prompt, "As Descartes said, I think, therefore", it will return the completion " I am" with high probability.
+
+### Swift
+
+```swift
+var yChat: YChat {
+ YChatCompanion.shared.create(apiKey: "your-api-key")
+}
+
+do {
+ let result = try await chatGpt.completion()
+ .setInput(input: "Say this is a test.")
+ .setMaxTokens(tokens: 1024)
+ .set... // you can set more parameters
+ .execute()
+} catch {
+ // catch any error that may occurs on api call.
+}
+```
+
+### Kotlin
+
+```kotlin
+val yChat by lazy {
+ YChat.create("your-api-key")
+}
+
+try {
+ val result = yChat.completion()
+ .setInput("Say this is a test.")
+ .setMaxTokens(1024)
+ .set... // you can set more parameters
+ .execute()
+
+} catch (e: exception) {
+ // catch any error that may occurs on api call.
+}
+```
+
+## ChatCompletions
+
+The chatCompletions api generates a list of chat completions for the given input message. It uses machine learning algorithms to generate responses that match the context or pattern provided in the input message.
+
+### Swift
+
+```swift
+var yChat: YChat {
+ YChatCompanion.shared.create(apiKey: "your-api-key")
+}
+
+do {
+ let result = try await chatGpt.chatCompletions()
+ .setMaxTokens(tokens: 1024)
+ .addMessage(
+ role: "assistant",
+ content: "You are a helpful assistant that only answers questions related to fitness"
+ )
+ .set... // you can set more parameters
+ .execute(content: "What is the best exercise for building muscle?")
+} catch {
+ // catch any error that may occurs on api call.
+}
+```
+
+### Kotlin
+
+```kotlin
+val yChat by lazy {
+ YChat.create("your-api-key")
+}
+
+try {
+ val result = yChat.chatCompletions()
+ .setMaxTokens(1024)
+ .addMessage(
+ role = "assistant",
+ content = "You are a helpful assistant that only answers questions related to fitness"
+ )
+ .set... // you can set more parameters
+ .execute("What is the best exercise for building muscle?")
+
+} catch (e: exception) {
+ // catch any error that may occurs on api call.
+}
+```
+
+## ImageGenerations
+
+The image generations api is used to generate images based on a prompt. You input some text as a prompt, and the model will generate one or more images.
+
+### Swift
+
+```swift
+var yChat: YChat {
+ YChatCompanion.shared.create(apiKey: "your-api-key")
+}
+
+do {
+ let result = try await chatGpt.imageGenerations()
+ .setResults(results: 2)
+ .setSize(size: "1024x1024")
+ .set... // you can set more parameters
+ .execute(prompt: "ocean")
+} catch {
+ // catch any error that may occurs on api call.
+}
+```
+
+### Kotlin
+
+```kotlin
+val yChat by lazy {
+ YChat.create("your-api-key")
+}
+
+try {
+ val result = yChat.imageGenerations()
+ .setResults(2)
+ .setSize("1024x1024")
+ .set... // you can set more parameters
+ .execute("ocean")
+
+} catch (e: exception) {
+ // catch any error that may occurs on api call.
+}
+```
+
+## Edits
+
+The edits api is used to edit prompts and re-generate. Given a prompt and an instruction, the model will return an edited version of the prompt.
+
+### Swift
+
+```swift
+var yChat: YChat {
+ YChatCompanion.shared.create(apiKey: "your-api-key")
+}
+
+do {
+ let result = try await chatGpt.edits()
+ .setInput(input: "What day of the wek is it?")
+ .setResults(result: 1)
+ .set... // you can set more parameters
+ .execute(instruction: "Fix the spelling mistakes")
+} catch {
+ // catch any error that may occurs on api call.
+}
+```
+
+### Kotlin
+
+```kotlin
+val yChat by lazy {
+ YChat.create("your-api-key")
+}
+
+try {
+ val result = yChat.edits()
+ .setInput("What day of the wek is it?")
+ .setResults(1)
+ .set... // you can set more parameters
+ .execute("Fix the spelling mistakes")
+
+} catch (e: exception) {
+ // catch any error that may occurs on api call.
+}
+```
\ No newline at end of file
diff --git a/sample/jvm/README.md b/sample/jvm/README.md
index fbe18d4..a1921c6 100644
--- a/sample/jvm/README.md
+++ b/sample/jvm/README.md
@@ -56,4 +56,19 @@ This endpoint generates images based on the provided prompt.
##### Example:
-`GET http://localhost:8080/api/ychat/generations?prompt="ocean"
\ No newline at end of file
+`GET http://localhost:8080/api/ychat/generations?prompt="ocean"
+
+### Edits Endpoint
+
+This endpoint edits the prompt based on the provided instruction.
+
+##### Endpoint: http://localhost:[port_number]/api/ychat/edits
+
+##### Parameters:
+
+- `input`: The input text to use as a starting point for the edit.
+- `instruction`: The instruction that tells the model how to edit the prompt.
+
+##### Example:
+
+`GET http://localhost:8080/api/ychat/edits?input=What day of the wek is it?&instruction=Fix the spelling mistakes
\ No newline at end of file
diff --git a/sample/jvm/src/main/java/co/yml/ychat/jvm/controller/YChatController.java b/sample/jvm/src/main/java/co/yml/ychat/jvm/controller/YChatController.java
index 05a3290..824580b 100644
--- a/sample/jvm/src/main/java/co/yml/ychat/jvm/controller/YChatController.java
+++ b/sample/jvm/src/main/java/co/yml/ychat/jvm/controller/YChatController.java
@@ -40,6 +40,15 @@ public ResponseEntity imageGenerations(
return ResponseEntity.ok(result);
}
+ @GetMapping("edits")
+ public ResponseEntity edits(
+ @RequestParam(value = "input") String input,
+ @RequestParam(value = "instruction") String instruction
+ ) throws Exception {
+ String result = YChatService.getEditsAnswer(input, instruction);
+ return ResponseEntity.ok(result);
+ }
+
private static class Defaults {
static final String COMPLETION_INPUT = "Say this is a test.";
static final String CHAT_COMPLETION_INPUT = "Tell me one strength exercise";
diff --git a/sample/jvm/src/main/java/co/yml/ychat/jvm/services/YChatService.java b/sample/jvm/src/main/java/co/yml/ychat/jvm/services/YChatService.java
index 6fa70fb..fe2f811 100644
--- a/sample/jvm/src/main/java/co/yml/ychat/jvm/services/YChatService.java
+++ b/sample/jvm/src/main/java/co/yml/ychat/jvm/services/YChatService.java
@@ -42,6 +42,14 @@ public String getImageGenerationsAnswer(String prompt) throws Exception {
return future.get().get(0);
}
+ public String getEditsAnswer(String input, String instruction) throws Exception {
+ final CompletableFuture> future = new CompletableFuture<>();
+ ychat.edits()
+ .setInput(input)
+ .execute(instruction, new CompletionCallbackResult<>(future));
+ return future.get().get(0);
+ }
+
private static class CompletionCallbackResult implements YChat.Callback {
private final CompletableFuture future;
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/YChat.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/YChat.kt
index c6e2286..fca0f34 100644
--- a/ychat/src/commonMain/kotlin/co/yml/ychat/YChat.kt
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/YChat.kt
@@ -2,6 +2,7 @@ package co.yml.ychat
import co.yml.ychat.entrypoint.features.ChatCompletions
import co.yml.ychat.entrypoint.features.Completion
+import co.yml.ychat.entrypoint.features.Edits
import co.yml.ychat.entrypoint.features.ImageGenerations
import co.yml.ychat.entrypoint.impl.YChatImpl
import kotlin.jvm.JvmStatic
@@ -86,13 +87,28 @@ interface YChat {
* ```
* val result = YChat.create(apiKey).imageGenerations()
* .setResults(2)
- * .setSize(1024x1024)
+ * .setSize("1024x1024")
* .set...
- * .execute("/image ocean")
+ * .execute("ocean")
* ```
*/
fun imageGenerations(): ImageGenerations
+ /**
+ * The edits api is used to edit prompts and re-generate. Given a prompt and an instruction,
+ * the model will return an edited version of the prompt.
+ *
+ * You can configure the parameters of the edits before executing it. Example:
+ * ```
+ * val result = YChat.create(apiKey).edits()
+ * .setInput("As Descartes said, I think, therefore")
+ * .setResults(1)
+ * .set...
+ * .execute("Fix spelling mistakes")
+ * ```
+ */
+ fun edits(): Edits
+
/**
* Callback is an interface used for handling the results of an operation.
* It provides two methods, `onSuccess` and `onError`, for handling the success
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/data/api/ChatGptApi.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/data/api/ChatGptApi.kt
index a7e3a9f..4c2226f 100644
--- a/ychat/src/commonMain/kotlin/co/yml/ychat/data/api/ChatGptApi.kt
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/data/api/ChatGptApi.kt
@@ -4,6 +4,8 @@ import co.yml.ychat.data.dto.ChatCompletionParamsDto
import co.yml.ychat.data.dto.ChatCompletionsDto
import co.yml.ychat.data.dto.CompletionDto
import co.yml.ychat.data.dto.CompletionParamsDto
+import co.yml.ychat.data.dto.EditsDto
+import co.yml.ychat.data.dto.EditsParamsDto
import co.yml.ychat.data.dto.ImageGenerationsDto
import co.yml.ychat.data.dto.ImageGenerationsParamsDto
import co.yml.ychat.data.infrastructure.ApiResult
@@ -15,4 +17,6 @@ internal interface ChatGptApi {
suspend fun chatCompletions(paramsDto: ChatCompletionParamsDto): ApiResult
suspend fun imageGenerations(paramsDto: ImageGenerationsParamsDto): ApiResult
+
+ suspend fun edits(paramsDto: EditsParamsDto): ApiResult
}
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/data/api/impl/ChatGptApiImpl.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/data/api/impl/ChatGptApiImpl.kt
index 791c8c2..44bb8b2 100644
--- a/ychat/src/commonMain/kotlin/co/yml/ychat/data/api/impl/ChatGptApiImpl.kt
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/data/api/impl/ChatGptApiImpl.kt
@@ -5,6 +5,8 @@ import co.yml.ychat.data.dto.ChatCompletionParamsDto
import co.yml.ychat.data.dto.ChatCompletionsDto
import co.yml.ychat.data.dto.CompletionDto
import co.yml.ychat.data.dto.CompletionParamsDto
+import co.yml.ychat.data.dto.EditsDto
+import co.yml.ychat.data.dto.EditsParamsDto
import co.yml.ychat.data.dto.ImageGenerationsDto
import co.yml.ychat.data.dto.ImageGenerationsParamsDto
import co.yml.ychat.data.infrastructure.ApiExecutor
@@ -36,4 +38,12 @@ internal class ChatGptApiImpl(private val apiExecutor: ApiExecutor) : ChatGptApi
.setBody(paramsDto)
.execute()
}
+
+ override suspend fun edits(paramsDto: EditsParamsDto): ApiResult {
+ return apiExecutor
+ .setEndpoint("v1/edits")
+ .setHttpMethod(HttpMethod.Post)
+ .setBody(paramsDto)
+ .execute()
+ }
}
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/EditsChoiceDto.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/EditsChoiceDto.kt
new file mode 100644
index 0000000..b72f7b7
--- /dev/null
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/EditsChoiceDto.kt
@@ -0,0 +1,12 @@
+package co.yml.ychat.data.dto
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+internal data class EditsChoiceDto(
+ @SerialName("text")
+ val text: String,
+ @SerialName("index")
+ val index: Int
+)
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/EditsDto.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/EditsDto.kt
new file mode 100644
index 0000000..b3cf82c
--- /dev/null
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/EditsDto.kt
@@ -0,0 +1,16 @@
+package co.yml.ychat.data.dto
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+internal data class EditsDto(
+ @SerialName("object")
+ val objectType: String,
+ @SerialName("created")
+ val created: Long,
+ @SerialName("choices")
+ val choices: List,
+ @SerialName("usage")
+ val usage: UsageDto,
+)
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/EditsParamsDto.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/EditsParamsDto.kt
new file mode 100644
index 0000000..0364563
--- /dev/null
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/EditsParamsDto.kt
@@ -0,0 +1,20 @@
+package co.yml.ychat.data.dto
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+internal data class EditsParamsDto(
+ @SerialName("model")
+ val model: String,
+ @SerialName("input")
+ val input: String,
+ @SerialName("instruction")
+ val instruction: String,
+ @SerialName("n")
+ val results: Int = 1,
+ @SerialName("temperature")
+ val temperature: Double,
+ @SerialName("top_p")
+ val topP: Double,
+)
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/domain/model/ImageGeneratedDto.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/ImageGeneratedDto.kt
similarity index 91%
rename from ychat/src/commonMain/kotlin/co/yml/ychat/domain/model/ImageGeneratedDto.kt
rename to ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/ImageGeneratedDto.kt
index 055f950..11b4b72 100644
--- a/ychat/src/commonMain/kotlin/co/yml/ychat/domain/model/ImageGeneratedDto.kt
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/ImageGeneratedDto.kt
@@ -1,4 +1,4 @@
-package co.yml.ychat.domain.model
+package co.yml.ychat.data.dto
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/ImageGenerationsDto.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/ImageGenerationsDto.kt
index 7f2d2e2..1169378 100644
--- a/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/ImageGenerationsDto.kt
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/data/dto/ImageGenerationsDto.kt
@@ -1,6 +1,5 @@
package co.yml.ychat.data.dto
-import co.yml.ychat.domain.model.ImageGeneratedDto
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/di/module/LibraryModule.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/di/module/LibraryModule.kt
index 7f1b5b7..f79e5a5 100644
--- a/ychat/src/commonMain/kotlin/co/yml/ychat/di/module/LibraryModule.kt
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/di/module/LibraryModule.kt
@@ -7,12 +7,15 @@ import co.yml.ychat.data.storage.ChatLogStorage
import co.yml.ychat.di.provider.NetworkProvider
import co.yml.ychat.domain.usecases.ChatCompletionsUseCase
import co.yml.ychat.domain.usecases.CompletionUseCase
+import co.yml.ychat.domain.usecases.EditsUseCase
import co.yml.ychat.domain.usecases.ImageGenerationsUseCase
import co.yml.ychat.entrypoint.features.ChatCompletions
import co.yml.ychat.entrypoint.features.Completion
+import co.yml.ychat.entrypoint.features.Edits
import co.yml.ychat.entrypoint.features.ImageGenerations
import co.yml.ychat.entrypoint.impl.ChatCompletionsImpl
import co.yml.ychat.entrypoint.impl.CompletionImpl
+import co.yml.ychat.entrypoint.impl.EditsImpl
import co.yml.ychat.entrypoint.impl.ImageGenerationsImpl
import kotlinx.coroutines.Dispatchers
import org.koin.core.module.Module
@@ -27,12 +30,14 @@ internal class LibraryModule(private val apiKey: String) {
factory { CompletionImpl(Dispatchers.Default, get()) }
factory { ChatCompletionsImpl(Dispatchers.Default, get()) }
factory { ImageGenerationsImpl(Dispatchers.Default, get()) }
+ factory { EditsImpl(Dispatchers.Default, get()) }
}
private val domainModule = module {
factory { CompletionUseCase(get(), get()) }
factory { ChatCompletionsUseCase(get()) }
factory { ImageGenerationsUseCase(get()) }
+ factory { EditsUseCase(get()) }
}
private val dataModule = module {
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/domain/mapper/EditsMapper.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/domain/mapper/EditsMapper.kt
new file mode 100644
index 0000000..86311b3
--- /dev/null
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/domain/mapper/EditsMapper.kt
@@ -0,0 +1,20 @@
+package co.yml.ychat.domain.mapper
+
+import co.yml.ychat.data.dto.EditsDto
+import co.yml.ychat.data.dto.EditsParamsDto
+import co.yml.ychat.domain.model.EditsParams
+
+internal fun EditsDto.toEditsModel(): List {
+ return this.choices.map { it.text }
+}
+
+internal fun EditsParams.toEditsParamsDto(): EditsParamsDto {
+ return EditsParamsDto(
+ model = this.model,
+ input = this.input,
+ instruction = this.instruction,
+ results = this.results,
+ temperature = this.temperature,
+ topP = this.topP
+ )
+}
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/domain/model/EditsParams.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/domain/model/EditsParams.kt
new file mode 100644
index 0000000..7b9797b
--- /dev/null
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/domain/model/EditsParams.kt
@@ -0,0 +1,10 @@
+package co.yml.ychat.domain.model
+
+internal data class EditsParams(
+ var model: String = "text-davinci-edit-001",
+ var input: String = "",
+ var instruction: String = "",
+ var results: Int = 1,
+ var temperature: Double = 1.0,
+ var topP: Double = 1.0,
+)
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/domain/usecases/EditsUseCase.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/domain/usecases/EditsUseCase.kt
new file mode 100644
index 0000000..68e62de
--- /dev/null
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/domain/usecases/EditsUseCase.kt
@@ -0,0 +1,15 @@
+package co.yml.ychat.domain.usecases
+
+import co.yml.ychat.data.api.ChatGptApi
+import co.yml.ychat.domain.mapper.toEditsModel
+import co.yml.ychat.domain.mapper.toEditsParamsDto
+import co.yml.ychat.domain.model.EditsParams
+
+internal data class EditsUseCase(private val chatGptApi: ChatGptApi) {
+
+ suspend fun requestEdits(params: EditsParams): List {
+ val requestDto = params.toEditsParamsDto()
+ val response = chatGptApi.edits(requestDto)
+ return response.getBodyOrThrow().toEditsModel()
+ }
+}
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/entrypoint/features/Edits.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/entrypoint/features/Edits.kt
new file mode 100644
index 0000000..9be2857
--- /dev/null
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/entrypoint/features/Edits.kt
@@ -0,0 +1,23 @@
+package co.yml.ychat.entrypoint.features
+
+import co.yml.ychat.YChat
+import co.yml.ychat.data.exception.ChatGptException
+import kotlin.coroutines.cancellation.CancellationException
+
+interface Edits {
+
+ fun setInput(input: String): Edits
+
+ fun setResults(results: Int): Edits
+
+ fun setModel(model: String): Edits
+
+ fun setTemperature(temperature: Double): Edits
+
+ fun setTopP(topP: Double): Edits
+
+ @Throws(CancellationException::class, ChatGptException::class)
+ suspend fun execute(instruction: String): List
+
+ fun execute(instruction: String, callback: YChat.Callback>)
+}
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/entrypoint/impl/EditsImpl.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/entrypoint/impl/EditsImpl.kt
new file mode 100644
index 0000000..fd1f2ea
--- /dev/null
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/entrypoint/impl/EditsImpl.kt
@@ -0,0 +1,58 @@
+package co.yml.ychat.entrypoint.impl
+
+import co.yml.ychat.YChat
+import co.yml.ychat.domain.model.EditsParams
+import co.yml.ychat.domain.usecases.EditsUseCase
+import co.yml.ychat.entrypoint.features.Edits
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.launch
+
+internal class EditsImpl(
+ private val dispatcher: CoroutineDispatcher,
+ private val editsUseCase: EditsUseCase
+) : Edits {
+
+ private val scope by lazy { CoroutineScope(SupervisorJob() + dispatcher) }
+
+ private var params: EditsParams = EditsParams()
+
+ override fun setInput(input: String): Edits {
+ params.input = input
+ return this
+ }
+
+ override fun setResults(results: Int): Edits {
+ params.results = results
+ return this
+ }
+
+ override fun setModel(model: String): Edits {
+ params.model = model
+ return this
+ }
+
+ override fun setTemperature(temperature: Double): Edits {
+ params.temperature = temperature
+ return this
+ }
+
+ override fun setTopP(topP: Double): Edits {
+ params.topP = topP
+ return this
+ }
+
+ override suspend fun execute(instruction: String): List {
+ params.instruction = instruction
+ return editsUseCase.requestEdits(params)
+ }
+
+ override fun execute(instruction: String, callback: YChat.Callback>) {
+ scope.launch {
+ runCatching { execute(instruction) }
+ .onSuccess { callback.onSuccess(it) }
+ .onFailure { callback.onError(it) }
+ }
+ }
+}
diff --git a/ychat/src/commonMain/kotlin/co/yml/ychat/entrypoint/impl/YChatImpl.kt b/ychat/src/commonMain/kotlin/co/yml/ychat/entrypoint/impl/YChatImpl.kt
index c29f71e..512b185 100644
--- a/ychat/src/commonMain/kotlin/co/yml/ychat/entrypoint/impl/YChatImpl.kt
+++ b/ychat/src/commonMain/kotlin/co/yml/ychat/entrypoint/impl/YChatImpl.kt
@@ -4,6 +4,7 @@ import co.yml.ychat.YChat
import co.yml.ychat.di.module.LibraryModule
import co.yml.ychat.entrypoint.features.ChatCompletions
import co.yml.ychat.entrypoint.features.Completion
+import co.yml.ychat.entrypoint.features.Edits
import co.yml.ychat.entrypoint.features.ImageGenerations
import org.koin.core.KoinApplication
@@ -27,4 +28,8 @@ internal class YChatImpl(apiKey: String) : YChat {
override fun imageGenerations(): ImageGenerations {
return koinApp.koin.get()
}
+
+ override fun edits(): Edits {
+ return koinApp.koin.get()
+ }
}
diff --git a/ychat/src/commonTest/kotlin/co/yml/ychat/di/LibraryModuleTest.kt b/ychat/src/commonTest/kotlin/co/yml/ychat/di/LibraryModuleTest.kt
index 214b693..8892d8f 100644
--- a/ychat/src/commonTest/kotlin/co/yml/ychat/di/LibraryModuleTest.kt
+++ b/ychat/src/commonTest/kotlin/co/yml/ychat/di/LibraryModuleTest.kt
@@ -9,6 +9,7 @@ import co.yml.ychat.domain.usecases.CompletionUseCase
import co.yml.ychat.domain.usecases.ImageGenerationsUseCase
import co.yml.ychat.entrypoint.features.ChatCompletions
import co.yml.ychat.entrypoint.features.Completion
+import co.yml.ychat.entrypoint.features.Edits
import co.yml.ychat.entrypoint.features.ImageGenerations
import io.ktor.client.HttpClient
import kotlin.test.AfterTest
@@ -43,5 +44,6 @@ class LibraryModuleTest : KoinTest {
get()
get()
get()
+ get()
}
}
diff --git a/ychat/src/commonTest/kotlin/co/yml/ychat/domain/mapper/EditsMapperTest.kt b/ychat/src/commonTest/kotlin/co/yml/ychat/domain/mapper/EditsMapperTest.kt
new file mode 100644
index 0000000..01465ff
--- /dev/null
+++ b/ychat/src/commonTest/kotlin/co/yml/ychat/domain/mapper/EditsMapperTest.kt
@@ -0,0 +1,34 @@
+package co.yml.ychat.domain.mapper
+
+import co.yml.ychat.data.dto.EditsChoiceDto
+import co.yml.ychat.data.dto.EditsDto
+import co.yml.ychat.data.dto.UsageDto
+import co.yml.ychat.domain.model.EditsParams
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class EditsMapperTest {
+
+ @Test
+ fun `on convert EditsDto to EditsModel`() {
+ val listOfChoicesDto = listOf(EditsChoiceDto("text 1", 1), EditsChoiceDto("text 2", 2))
+ val editsDto = EditsDto(
+ created = 12345,
+ objectType = "edit",
+ choices = listOfChoicesDto,
+ usage = UsageDto(1, 1, 1)
+ )
+ assertEquals(listOfChoicesDto.map { it.text }, editsDto.toEditsModel())
+ }
+
+ @Test
+ fun `on convert EditsParams to EditsDto`() {
+ val editsParams = EditsParams(input = "this is a test")
+ assertEquals("text-davinci-edit-001", editsParams.toEditsParamsDto().model)
+ assertEquals("this is a test", editsParams.toEditsParamsDto().input)
+ assertEquals("", editsParams.toEditsParamsDto().instruction)
+ assertEquals(1, editsParams.toEditsParamsDto().results)
+ assertEquals(1.0, editsParams.toEditsParamsDto().temperature)
+ assertEquals(1.0, editsParams.toEditsParamsDto().topP)
+ }
+}
diff --git a/ychat/src/commonTest/kotlin/co/yml/ychat/domain/mapper/ImageGenerationsMapperTest.kt b/ychat/src/commonTest/kotlin/co/yml/ychat/domain/mapper/ImageGenerationsMapperTest.kt
index 0ce66ff..7e1abb0 100644
--- a/ychat/src/commonTest/kotlin/co/yml/ychat/domain/mapper/ImageGenerationsMapperTest.kt
+++ b/ychat/src/commonTest/kotlin/co/yml/ychat/domain/mapper/ImageGenerationsMapperTest.kt
@@ -1,7 +1,7 @@
package co.yml.ychat.domain.mapper
import co.yml.ychat.data.dto.ImageGenerationsDto
-import co.yml.ychat.domain.model.ImageGeneratedDto
+import co.yml.ychat.data.dto.ImageGeneratedDto
import co.yml.ychat.domain.model.ImageGenerationsParams
import kotlin.test.Test
import kotlin.test.assertEquals
diff --git a/ychat/src/commonTest/kotlin/co/yml/ychat/domain/model/EditsParamsTest.kt b/ychat/src/commonTest/kotlin/co/yml/ychat/domain/model/EditsParamsTest.kt
new file mode 100644
index 0000000..d661d86
--- /dev/null
+++ b/ychat/src/commonTest/kotlin/co/yml/ychat/domain/model/EditsParamsTest.kt
@@ -0,0 +1,21 @@
+package co.yml.ychat.domain.model
+
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class EditsParamsTest {
+
+ @Test
+ fun `on EditsParams verify default values`() {
+ // arrange
+ val params = EditsParams()
+
+ // assert
+ assertEquals("text-davinci-edit-001", params.model)
+ assertEquals("", params.input)
+ assertEquals("", params.instruction)
+ assertEquals(1, params.results)
+ assertEquals(1.0, params.temperature)
+ assertEquals(1.0, params.topP)
+ }
+}
diff --git a/ychat/src/commonTest/kotlin/co/yml/ychat/domain/model/ImageGenerationsParamsTest.kt b/ychat/src/commonTest/kotlin/co/yml/ychat/domain/model/ImageGenerationsParamsTest.kt
index 0c237cf..bf28863 100644
--- a/ychat/src/commonTest/kotlin/co/yml/ychat/domain/model/ImageGenerationsParamsTest.kt
+++ b/ychat/src/commonTest/kotlin/co/yml/ychat/domain/model/ImageGenerationsParamsTest.kt
@@ -6,7 +6,7 @@ import kotlin.test.assertEquals
class ImageGenerationsParamsTest {
@Test
- fun `on ChatCompletionsParams verify default values`() {
+ fun `on ImageGenerationsParams verify default values`() {
// arrange
val params = ImageGenerationsParams()
diff --git a/ychat/src/commonTest/kotlin/co/yml/ychat/domain/usecases/EditsUseCaseTest.kt b/ychat/src/commonTest/kotlin/co/yml/ychat/domain/usecases/EditsUseCaseTest.kt
new file mode 100644
index 0000000..a447def
--- /dev/null
+++ b/ychat/src/commonTest/kotlin/co/yml/ychat/domain/usecases/EditsUseCaseTest.kt
@@ -0,0 +1,68 @@
+package co.yml.ychat.domain.usecases
+
+import co.yml.ychat.data.api.ChatGptApi
+import co.yml.ychat.data.dto.EditsChoiceDto
+import co.yml.ychat.data.dto.EditsDto
+import co.yml.ychat.data.dto.UsageDto
+import co.yml.ychat.data.exception.ChatGptException
+import co.yml.ychat.data.infrastructure.ApiResult
+import co.yml.ychat.domain.model.EditsParams
+import io.mockk.coEvery
+import io.mockk.mockk
+import kotlinx.coroutines.runBlocking
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class EditsUseCaseTest {
+
+ private lateinit var editsUseCase: EditsUseCase
+
+ private val chatGptApiMock = mockk()
+
+ @BeforeTest
+ fun setup() {
+ editsUseCase = EditsUseCase(chatGptApiMock)
+ }
+
+ @Test
+ fun `on requestEdits when request succeed then should return formatted result`() {
+ // arrange
+ val prompt = "write text"
+ val editsDto = buildEditsDto(listOf("text 1", "text 2"))
+ val params = EditsParams(input = prompt, results = 2)
+ val apiResult = ApiResult(body = editsDto)
+ coEvery { chatGptApiMock.edits(any()) } returns apiResult
+
+ // act
+ val result = runBlocking { editsUseCase.requestEdits(params) }
+
+ // assert
+ assertEquals("text 2", result.last())
+ }
+
+ @Test
+ fun `on requestEdits when not request succeed then should throw an exception`() {
+ // arrange
+ val prompt = "text"
+ val params = EditsParams(input = prompt)
+ val apiResult = ApiResult(exception = ChatGptException())
+ coEvery { chatGptApiMock.edits(any()) } returns apiResult
+
+ // act
+ val result =
+ runCatching { runBlocking { editsUseCase.requestEdits(params) } }
+
+ // assert
+ assertEquals(true, result.exceptionOrNull() is ChatGptException)
+ }
+
+ private fun buildEditsDto(texts: List): EditsDto {
+ return EditsDto(
+ created = 12345,
+ objectType = "edits",
+ choices = listOf(EditsChoiceDto(text = texts[0], index = 1), EditsChoiceDto(text = texts[1], index = 2)),
+ usage = UsageDto(1, 1, 1)
+ )
+ }
+}
diff --git a/ychat/src/commonTest/kotlin/co/yml/ychat/domain/usecases/ImageGenerationsUseCaseTest.kt b/ychat/src/commonTest/kotlin/co/yml/ychat/domain/usecases/ImageGenerationsUseCaseTest.kt
index ad1ffe7..b9671fd 100644
--- a/ychat/src/commonTest/kotlin/co/yml/ychat/domain/usecases/ImageGenerationsUseCaseTest.kt
+++ b/ychat/src/commonTest/kotlin/co/yml/ychat/domain/usecases/ImageGenerationsUseCaseTest.kt
@@ -4,7 +4,7 @@ import co.yml.ychat.data.api.ChatGptApi
import co.yml.ychat.data.dto.ImageGenerationsDto
import co.yml.ychat.data.exception.ChatGptException
import co.yml.ychat.data.infrastructure.ApiResult
-import co.yml.ychat.domain.model.ImageGeneratedDto
+import co.yml.ychat.data.dto.ImageGeneratedDto
import co.yml.ychat.domain.model.ImageGenerationsParams
import io.mockk.coEvery
import io.mockk.mockk
diff --git a/ychat/src/commonTest/kotlin/co/yml/ychat/entrypoint/YChatTest.kt b/ychat/src/commonTest/kotlin/co/yml/ychat/entrypoint/YChatTest.kt
index 0b5be31..c8e195c 100644
--- a/ychat/src/commonTest/kotlin/co/yml/ychat/entrypoint/YChatTest.kt
+++ b/ychat/src/commonTest/kotlin/co/yml/ychat/entrypoint/YChatTest.kt
@@ -93,6 +93,28 @@ class YChatTest {
assertEquals("https://testlink.com/image-test.jpg", result.first())
}
+ @Test
+ fun `on edits execute method should return result successfully`() {
+ // arrange
+ val expectedResult = "What day of the week is it?"
+ val imageGenerationsSuccessResult = MockStorage.editsSuccessResult(expectedResult)
+ mockHttpEngine(imageGenerationsSuccessResult)
+
+ // act
+ val result = runBlocking {
+ yChat.edits()
+ .setResults(1)
+ .setTemperature(1.0)
+ .setModel("model-1")
+ .setTopP(1.0)
+ .setInput("What day of the wek is it?")
+ .execute("Fix the spelling mistakes")
+ }
+
+ // assert
+ assertEquals(expectedResult, result.first())
+ }
+
private fun mockHttpEngine(result: String) {
val httpEngine = MockEngine {
respond(
diff --git a/ychat/src/commonTest/kotlin/infrastructure/MockStorage.kt b/ychat/src/commonTest/kotlin/infrastructure/MockStorage.kt
index 95d843f..7e361c7 100644
--- a/ychat/src/commonTest/kotlin/infrastructure/MockStorage.kt
+++ b/ychat/src/commonTest/kotlin/infrastructure/MockStorage.kt
@@ -16,4 +16,8 @@ object MockStorage {
fun imageGenerationsSuccessResult(text: String) =
"{\"created\":1678805561,\"data\":[{\"url\":\"$text\"}]}"
+
+ fun editsSuccessResult(text: String) = "{\"object\":\"edit\",\"created\":1679072839," +
+ "\"choices\":[{\"text\":\"$text\",\"index\":0}]," +
+ "\"usage\":{\"prompt_tokens\":25,\"completion_tokens\":28,\"total_tokens\":53}}"
}