Skip to content

Commit

Permalink
[ Add ] exposed enabling web mode to use fetch client with the package
Browse files Browse the repository at this point in the history
  • Loading branch information
anasfik committed Nov 17, 2023
1 parent 45bb0be commit 4d19e3c
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 17 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,22 @@ You can change the base url used in the package to your own, this can be helpful
OpenAI.baseUrl = "https://api.openai.com/v1"; // the default one.
```

### Configure the package for web environment (Flutter Web)

because the package uses the [http](https://pub.dev/packages/http) package, the streaming functionality will not work as expected for the Streaming methods, to get over this, you will need to let the package knows that you are using it in a web environment, Flutter as example exposes the `kIsWeb` property that you can use to check if you are in a web environment or not, just assign it to `OpenAI.isWeb`

```dart
// import it from flutter/foundation.dart
import 'package:flutter/foundation.dart' show kIsWeb;
void main() {
// ...
OpenAI.isWeb = kIsWeb;
runApp(MyApp());
}
```

## Models

### List Models
Expand Down
7 changes: 7 additions & 0 deletions example/lib/setting_for_web_env.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'package:dart_openai/dart_openai.dart';

void main() {
OpenAI.isWeb = true;

print(OpenAI.isWeb);
}
14 changes: 14 additions & 0 deletions lib/src/core/constants/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ abstract class OpenAIConfig {
/// {@endtemplate}
static String? _baseUrl;

/// {@template openai_config_is_web}
/// This is a flag that indicates if the library is running on the web or not.
/// {@endtemplate}
static bool _isWeb = false;

/// This is the version of the API.
static String get version => OpenAIStrings.version;

Expand All @@ -30,9 +35,18 @@ abstract class OpenAIConfig {
return _baseUrl ?? OpenAIStrings.defaultBaseUrl;
}

/// {@macro openai_config_is_web}
static bool get isWeb => _isWeb;

@internal
static set baseUrl(String? baseUrl) {
_baseUrl = baseUrl;
OpenAILogger.logBaseUrl(_baseUrl);
}

@internal
static set isWeb(bool isWeb) {
_isWeb = isWeb;
OpenAILogger.logIsWeb(_isWeb);
}
}
17 changes: 11 additions & 6 deletions lib/src/core/networking/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ import "dart:convert";
import "dart:io";
import "package:dart_openai/src/core/constants/config.dart";
import "package:dart_openai/src/core/utils/extensions.dart";
// ignore: unused_import
import "package:dart_openai/src/core/utils/http_client_web.dart"
if (dart.library.js) "package:dart_openai/src/core/utils/http_client_web.dart"
if (dart.library.io) "package:dart_openai/src/core/utils/http_client_io.dart";

import 'package:dart_openai/dart_openai.dart';
import "package:dart_openai/src/core/builder/headers.dart";
Expand All @@ -15,6 +11,7 @@ import "package:http/http.dart" as http;
import "package:meta/meta.dart";

import '../constants/strings.dart';
import "../utils/streaming_http_client.dart";

/// Handling exceptions returned by OpenAI Stream API.
final class _OpenAIChatStreamSink implements EventSink<String> {
Expand Down Expand Up @@ -140,7 +137,7 @@ abstract class OpenAINetworkingClient {
}) {
final controller = StreamController<T>();

final clientForUse = client ?? http.Client();
final clientForUse = client ?? _streamingHttpClient();

final uri = Uri.parse(from);

Expand Down Expand Up @@ -336,7 +333,7 @@ abstract class OpenAINetworkingClient {
final controller = StreamController<T>();

try {
final clientForUse = client ?? http.Client();
final clientForUse = client ?? _streamingHttpClient();

final uri = Uri.parse(to);

Expand Down Expand Up @@ -661,4 +658,12 @@ abstract class OpenAINetworkingClient {
static bool doesErrorExists(Map<String, dynamic> decodedResponseBody) {
return decodedResponseBody[OpenAIStrings.errorFieldKey] != null;
}

static http.Client _streamingHttpClient() {
if (OpenAIConfig.isWeb) {
return createWebClient();
} else {
return createIoClient();
}
}
}
3 changes: 0 additions & 3 deletions lib/src/core/utils/http_client_io.dart

This file was deleted.

5 changes: 0 additions & 5 deletions lib/src/core/utils/http_client_web.dart

This file was deleted.

4 changes: 4 additions & 0 deletions lib/src/core/utils/logger.dart
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,8 @@ abstract final class OpenAILogger {
static void requestsTimeoutChanged(Duration requestsTimeOut) {
return log("requests timeout changed to $requestsTimeOut");
}

static void logIsWeb(bool isWeb) {
return log("isWeb set to $isWeb");
}
}
7 changes: 7 additions & 0 deletions lib/src/core/utils/streaming_http_client.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'package:fetch_client/fetch_client.dart' as fetch;
import 'package:http/http.dart' as http;

fetch.FetchClient createWebClient() =>
fetch.FetchClient(mode: fetch.RequestMode.cors);

http.Client createIoClient() => http.Client();
15 changes: 15 additions & 0 deletions lib/src/instance/openai.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ final class OpenAI extends OpenAIClientBase {
/// {@macro openai_config_requests_timeOut}
static Duration get requestsTimeOut => OpenAIConfig.requestsTimeOut;

/// {@macro openai_config_is_web}
static bool get isWeb => OpenAIConfig.isWeb;

/// The [OpenAIModel] instance, used to access the model endpoints.
/// Please, refer to the Models page from the official OpenAI documentation website in order to know what models are available and what's the use case of every model.
OpenAIModel get model => OpenAIModel();
Expand Down Expand Up @@ -138,6 +141,18 @@ final class OpenAI extends OpenAIClientBase {
OpenAILogger.isActive = newValue;
}

/// Wether the package is running on the web or not, example of this is the use of Flutter web.
///
/// By default it is set to [false].
///
/// ```dart
/// OpenAI.isWeb = kIsWeb;
/// ```
///
static set isWeb(bool newValue) {
OpenAIConfig.isWeb = newValue;
}

// /// Sets the given [client] as the new client that will be used in the requests made by the package.
// ///
// /// Example:
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ dependencies:
http: ^1.1.0
meta: ^1.9.1
collection: ^1.17.2
fetch_client: ^1.0.0
fetch_client: ^1.0.2

dev_dependencies:
dart_code_metrics: ^4.19.2
Expand Down
17 changes: 15 additions & 2 deletions test/openai_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ void main() async {
// ! this is to reset the base URL to the default one.
OpenAI.baseUrl = OpenAIStrings.defaultBaseUrl;
});

test("switching showing logs", () {
OpenAI.showLogs = true;
expect(OpenAILogger.isActive, isTrue);
Expand All @@ -80,18 +81,30 @@ void main() async {
});

test("requests timeout", () {
OpenAIConfig.requestsTimeOut = Duration(seconds: 10);
final tS = 10;

OpenAIConfig.requestsTimeOut = Duration(seconds: tS);

expect(
OpenAIConfig.requestsTimeOut.inMilliseconds,
Duration(seconds: 10).inMilliseconds,
Duration(seconds: tS).inMilliseconds,
);

//! return to the default timeout.

OpenAIConfig.requestsTimeOut = OpenAIConfig.defaultRequestsTimeOut;
});

test('declaring web environment for the package', () {
OpenAI.isWeb = true;

expect(OpenAI.isWeb, isTrue);

// ! this is to reset the isWeb to the default one.
OpenAI.isWeb = false;
});
});

group('models', () {
test(
'list models',
Expand Down

0 comments on commit 4d19e3c

Please sign in to comment.