From 3ccbb860fc043f8f656d9111e2de5b2b890d0d28 Mon Sep 17 00:00:00 2001 From: "redev.rx" Date: Wed, 24 Jan 2024 15:02:44 +0700 Subject: [PATCH] feat: chat complete image input --- README.md | 88 +++++++++++++------ example/lib/main.dart | 84 ++++++++++++------ .../lib/bloc/openai/openai_bloc.dart | 1 + lib/src/assistants.dart | 12 +++ .../model/chat_complete/enum/chat_model.dart | 4 + .../request/chat_complete_text.dart | 63 +++++-------- .../chat_complete/request/function_data.dart | 1 + .../request/chat_complete_text_test.dart | 30 +++---- test/openai_test.dart | 26 +++--- 9 files changed, 182 insertions(+), 127 deletions(-) diff --git a/README.md b/README.md index 00ccac4..a54e849 100644 --- a/README.md +++ b/README.md @@ -204,7 +204,7 @@ FutureBuilder( void chatComplete() async { final request = ChatCompleteText(messages: [ Map.of({"role": "user", "content": 'Hello!'}) - ], maxToken: 200, model: GptTurbo0301ChatModel()); + ], maxToken: 200, model: Gpt41106PreviewChatModel()); final response = await openAI.onChatCompletion(request: request); for (var element in response!.choices) { @@ -216,37 +216,69 @@ FutureBuilder( - Chat Complete Function Calling ```dart -/// work only with gpt-turbo-0613,gpt-4-0613 void gptFunctionCalling() async { + final request = ChatCompleteText( + messages: [ + Messages( + role: Role.user, + content: "What is the weather like in Boston?", + name: "get_current_weather"), + ], + maxToken: 200, + model: Gpt41106PreviewChatModel(), + tools: [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA" + }, + "unit": { + "type": "string", + "enum": ["celsius", "fahrenheit"] + } + }, + "required": ["location"] + } + } + } + ], + toolChoice: 'auto', + ); + + ChatCTResponse? response = await openAI.onChatCompletion(request: request); +} +``` + +- Chat Complete Image Input + +```dart + void imageInput() async { final request = ChatCompleteText( - messages: [ - Messages( - role: Role.user, content: "What is the weather like in Boston?",name: "get_current_weather"), - ], - maxToken: 200, - model: GptTurbo0631Model(), - functions: [ - FunctionData( - name: "get_current_weather", - description: "Get the current weather in a given location", - parameters: { - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "The city and state, e.g. San Francisco, CA" - }, - "unit": { - "type": "string", - "enum": ["celsius", "fahrenheit"] - } - }, - "required": ["location"] - }) - ], - functionCall: FunctionCall.auto); + messages: [ + { + "role": "user", + "content": [ + {"type": "text", "text": "What’s in this image?"}, + { + "type": "image_url", + "image_url": {"url": "image-url"} + } + ] + } + ], + maxToken: 200, + model: Gpt4VisionPreviewChatModel(), + ); ChatCTResponse? response = await openAI.onChatCompletion(request: request); + debugPrint("$response"); } ``` diff --git a/example/lib/main.dart b/example/lib/main.dart index 2f7fea2..bac6fe4 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -45,34 +45,62 @@ class _TranslateScreenState extends State { ///parameter name is require void gptFunctionCalling() async { final request = ChatCompleteText( - messages: [ - Messages( - role: Role.user, - content: "What is the weather like in Boston?", - name: "get_current_weather"), - ], - maxToken: 200, - model: GptTurbo0631Model(), - functions: [ - FunctionData( - name: "get_current_weather", - description: "Get the current weather in a given location", - parameters: { - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "The city and state, e.g. San Francisco, CA" - }, - "unit": { - "type": "string", - "enum": ["celsius", "fahrenheit"] - } + messages: [ + Messages( + role: Role.user, + content: "What is the weather like in Boston?", + name: "get_current_weather") + .toJson(), + ], + maxToken: 200, + model: Gpt41106PreviewChatModel(), + tools: [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA" }, - "required": ["location"] - }) - ], - functionCall: FunctionCall.auto); + "unit": { + "type": "string", + "enum": ["celsius", "fahrenheit"] + } + }, + "required": ["location"] + } + } + } + ], + toolChoice: 'auto', + ); + + ChatCTResponse? response = await openAI.onChatCompletion(request: request); + debugPrint("$response"); + } + + void imageInput() async { + final request = ChatCompleteText( + messages: [ + { + "role": "user", + "content": [ + {"type": "text", "text": "What’s in this image?"}, + { + "type": "image_url", + "image_url": {"url": "image-url"} + } + ] + } + ], + maxToken: 200, + model: Gpt4VisionPreviewChatModel(), + ); ChatCTResponse? response = await openAI.onChatCompletion(request: request); debugPrint("$response"); @@ -80,7 +108,7 @@ class _TranslateScreenState extends State { void gpt4() async { final request = ChatCompleteText(messages: [ - Messages(role: Role.assistant, content: 'Hello!'), + Messages(role: Role.assistant, content: 'Hello!').toJson(), ], maxToken: 200, model: Gpt4ChatModel()); await openAI.onChatCompletion(request: request); diff --git a/example_app/openai_app/lib/bloc/openai/openai_bloc.dart b/example_app/openai_app/lib/bloc/openai/openai_bloc.dart index f8f95d2..1530483 100644 --- a/example_app/openai_app/lib/bloc/openai/openai_bloc.dart +++ b/example_app/openai_app/lib/bloc/openai/openai_bloc.dart @@ -118,6 +118,7 @@ class OpenAIBloc extends Cubit { model: _getVersion() ? Gpt4ChatModel() : GptTurboChatModel(), messages: [ Messages(role: Role.user, content: getTextInput().value.text) + .toJson(), ], maxToken: 400); diff --git a/lib/src/assistants.dart b/lib/src/assistants.dart index 3f72245..8937b72 100644 --- a/lib/src/assistants.dart +++ b/lib/src/assistants.dart @@ -3,4 +3,16 @@ import 'client/client.dart'; class Assistants { final OpenAIClient _client; Assistants(this._client); + + void create() { + _client.get( + 'url', + onSuccess: (p0) { + return; + }, + onCancel: (cancelData) { + return; + }, + ); + } } diff --git a/lib/src/model/chat_complete/enum/chat_model.dart b/lib/src/model/chat_complete/enum/chat_model.dart index 2d03d85..6a465c0 100644 --- a/lib/src/model/chat_complete/enum/chat_model.dart +++ b/lib/src/model/chat_complete/enum/chat_model.dart @@ -53,6 +53,10 @@ class Gpt4VisionPreviewChatModel extends ChatModel { Gpt4VisionPreviewChatModel() : super(model: kGpt4VisionPreview); } +class Gpt41106PreviewChatModel extends ChatModel { + Gpt41106PreviewChatModel() : super(model: kGpt41106Preview); +} + // enum ChatModel { // gptTurbo, // diff --git a/lib/src/model/chat_complete/request/chat_complete_text.dart b/lib/src/model/chat_complete/request/chat_complete_text.dart index c6470a3..e34dd2f 100644 --- a/lib/src/model/chat_complete/request/chat_complete_text.dart +++ b/lib/src/model/chat_complete/request/chat_complete_text.dart @@ -1,7 +1,6 @@ import 'package:chat_gpt_sdk/src/model/chat_complete/enum/chat_model.dart'; import 'package:chat_gpt_sdk/src/model/chat_complete/enum/function_call.dart'; import 'package:chat_gpt_sdk/src/model/chat_complete/request/function_data.dart'; -import 'package:chat_gpt_sdk/src/model/chat_complete/request/messages.dart'; import 'package:chat_gpt_sdk/src/model/chat_complete/request/response_format.dart'; class ChatCompleteText { @@ -23,7 +22,7 @@ class ChatCompleteText { ///The messages to generate chat completions for, /// in the chat format. [messages] - final List messages; + final List> messages; ///A list of functions the model may generate JSON inputs for. ///[functions] @@ -197,47 +196,25 @@ class ChatCompleteText { Map toJson() { Map json; - json = model is Gpt40631ChatModel || model is GptTurbo0631Model - ? Map.of({ - "model": model.model, - "messages": messages.map((e) => e.toJsonFunctionStruct()).toList(), - // "functions": functions?.map((e) => e.toJson()).toList(), - // "function_call": functionCall?.name, - "temperature": temperature, - "top_p": topP, - "n": n, - "stream": stream, - "stop": stop, - "max_tokens": maxToken, - "presence_penalty": presencePenalty, - "frequency_penalty": frequencyPenalty, - "user": user, - "response_format": responseFormat?.toJson(), - "logit_bias": logitBias, - "logprobs": logprobs, - "top_logprobs": topLogprobs, - "seed": seed, - "tool_choice": toolChoice, - }) - : Map.of({ - "model": model.model, - "messages": messages.map((e) => e.toJson()).toList(), - "temperature": temperature, - "top_p": topP, - "n": n, - "stream": stream, - "stop": stop, - "max_tokens": maxToken, - "presence_penalty": presencePenalty, - "frequency_penalty": frequencyPenalty, - "user": user, - "response_format": responseFormat?.toJson(), - "logit_bias": logitBias, - "logprobs": logprobs, - "top_logprobs": topLogprobs, - "seed": seed, - "tool_choice": toolChoice, - }) + json = Map.of({ + "model": model.model, + "messages": messages, + "temperature": temperature, + "top_p": topP, + "n": n, + "stream": stream, + "stop": stop, + "max_tokens": maxToken, + "presence_penalty": presencePenalty, + "frequency_penalty": frequencyPenalty, + "user": user, + "response_format": responseFormat?.toJson(), + "logit_bias": logitBias, + "logprobs": logprobs, + "top_logprobs": topLogprobs, + "seed": seed, + "tool_choice": toolChoice, + }) ..removeWhere((key, value) => value == null); return json; diff --git a/lib/src/model/chat_complete/request/function_data.dart b/lib/src/model/chat_complete/request/function_data.dart index 6cc8215..7d9bca2 100644 --- a/lib/src/model/chat_complete/request/function_data.dart +++ b/lib/src/model/chat_complete/request/function_data.dart @@ -1,3 +1,4 @@ +@Deprecated('') class FunctionData { ///The name of the function to be called. /// Must be a-z, A-Z, 0-9, or contain underscores diff --git a/test/model/chat_complete/request/chat_complete_text_test.dart b/test/model/chat_complete/request/chat_complete_text_test.dart index d0d0548..4307fc5 100644 --- a/test/model/chat_complete/request/chat_complete_text_test.dart +++ b/test/model/chat_complete/request/chat_complete_text_test.dart @@ -9,7 +9,7 @@ void main() { role: Role.user, content: 'Hello', name: 'function_name', - ), + ).toJson(), ]; final chatCompleteText = ChatCompleteText( @@ -57,21 +57,21 @@ void main() { role: Role.user, content: 'Hello', name: 'function_name', - ), + ).toJson(), Messages( role: Role.assistant, content: 'Hi, how can I assist you today?', name: 'function_name', - ), - ], - functionCall: FunctionCall.auto, - functions: [ - FunctionData( - name: 'function_name', - description: '', - parameters: Map.of({}), - ), + ).toJson(), ], + // functionCall: FunctionCall.auto, + // functions: [ + // FunctionData( + // name: 'function_name', + // description: '', + // parameters: Map.of({}), + // ), + // ], ); final expectedJson = { @@ -88,10 +88,10 @@ void main() { 'name': 'function_name', }, ], - 'functions': [ - {'name': 'function_name', 'description': '', 'parameters': {}}, - ], - 'function_call': 'auto', + // 'functions': [ + // {'name': 'function_name', 'description': '', 'parameters': {}}, + // ], + // 'function_call': 'auto', 'temperature': 0.3, 'top_p': 1.0, 'n': 1, diff --git a/test/openai_test.dart b/test/openai_test.dart index 89e1516..b4447af 100644 --- a/test/openai_test.dart +++ b/test/openai_test.dart @@ -50,7 +50,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: Gpt4ChatModel(), @@ -315,7 +315,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: GptTurboChatModel(), @@ -342,7 +342,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: GptTurboChatModel(), @@ -375,7 +375,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: GptTurbo0301ChatModel(), @@ -396,7 +396,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: Gpt4ChatModel(), @@ -423,7 +423,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: Gpt4ChatModel(), @@ -456,7 +456,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: Gpt4ChatModel(), @@ -477,7 +477,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: GptTurboChatModel(), @@ -506,7 +506,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: GptTurboChatModel(), @@ -538,7 +538,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: GptTurbo0301ChatModel(), @@ -557,7 +557,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: Gpt4ChatModel(), @@ -586,7 +586,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: Gpt4ChatModel(), @@ -618,7 +618,7 @@ void main() async { Messages( role: Role.user, content: "Hello", - ), + ).toJson(), ], maxToken: 200, model: Gpt4ChatModel(),