From 6da8d848a80cd7bfb1f215ac7bfde1320a6aadb6 Mon Sep 17 00:00:00 2001 From: Pun Butrach Date: Sat, 24 Feb 2024 05:37:26 +0000 Subject: [PATCH] Initial prototype phase of WA AI Dart --- .gitignore | 7 ++ CHANGELOG.md | 2 + README.md | 11 +--- analysis_options.yaml | 30 +++++++++ docs/CONTRIBUTING.md | 18 ++++++ lib/src/api.dart | 147 ++++++++++++++++++++++++++++++++++++++++++ lib/src/error.dart | 21 ++++++ lib/wolframalpha.dart | 5 ++ pubspec.yaml | 22 +++++++ test/api_test.dart | 28 ++++++++ 10 files changed, 283 insertions(+), 8 deletions(-) create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 analysis_options.yaml create mode 100644 docs/CONTRIBUTING.md create mode 100644 lib/src/api.dart create mode 100644 lib/src/error.dart create mode 100644 lib/wolframalpha.dart create mode 100644 pubspec.yaml create mode 100644 test/api_test.dart diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3cceda5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# https://dart.dev/guides/libraries/private-files +# Created by `dart pub` +.dart_tool/ + +# Avoid committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d79679f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,2 @@ +## 0.0.1 +Prototype stage of Wolfram|Alpha AI Dart client. diff --git a/README.md b/README.md index 8f40467..d35a6d2 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,4 @@ -# 🚀 Template for New Project -This repository only contains a template that can be used to create a repository -for new punExperiment project. +# 🌀 WolframAlpha API (Dart) -Settings for this template: -* License: Apache 2.0 -* Code of Conduct: Contributor Covenant 2.1 -* CI - - [addlicense v1.1.1](https://github.com/google/addlicense/releases/tag/v1.1.1) +> [!CAUTION] +> This project is in Prototype phase, the implementation is all using the demo API. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..dee8927 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,30 @@ +# This file configures the static analysis results for your project (errors, +# warnings, and lints). +# +# This enables the 'recommended' set of lints from `package:lints`. +# This set helps identify many issues that may lead to problems when running +# or consuming Dart code, and enforces writing Dart using a single, idiomatic +# style and format. +# +# If you want a smaller set of lints you can change this to specify +# 'package:lints/core.yaml'. These are just the most critical lints +# (the recommended set includes the core lints). +# The core lints are also what is used by pub.dev for scoring packages. + +include: package:lints/recommended.yaml + +# Uncomment the following section to specify additional rules. + +# linter: +# rules: +# - camel_case_types + +# analyzer: +# exclude: +# - path/to/excluded/files/** + +# For more information about the core and recommended set of lints, see +# https://dart.dev/go/core-lints + +# For additional information about configuring this file, see +# https://dart.dev/guides/language/analysis-options diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 0000000..b74642a --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,18 @@ +# `> WA_Dart // Contributing` +Thanks you for your interest in contributing. Please check out the [Code of Conduct](CODE_OF_CONDUCT.md) before contributing, thank you! + +> [!IMPORTANT] +> This guide assume that you already installed Dart 3.3.0 or higher. + +Building the script: +1. Clone the repository: `git@github.com:BoringExperiments/WolframAlpha_ai_dart.git` +2. Install the required dependencies: `dart pub get` +3. Build the script: `dart build` + +Development tools: +- Analysis check: `dart analyze` +- Test: `dart test` + +Here are some tip when contributing: +- [Signing commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits) are highly recommended. +- This repository follows the [Effective Dart](https://dart.dev/effective-dart) guide **but not strictly enforced**. diff --git a/lib/src/api.dart b/lib/src/api.dart new file mode 100644 index 0000000..85e509b --- /dev/null +++ b/lib/src/api.dart @@ -0,0 +1,147 @@ +import 'package:dio/dio.dart'; +import 'error.dart'; + +final options = BaseOptions( + baseUrl: 'https://api.wolframalpha.com', + headers: {'User-Agent': 'WA-Dart-client/0.0.1'}, +); + +final dio = Dio(options); + +// Return simplified information using image data. +dynamic simple({ + required String appId, + required String input, + // String? units, + // int? width, + // int? fontSize, + // String? background, + // String? foreground, + // String? layout, + int? timeout = 5, +}) async { + Response response; + response = await dio.request( + '/v1/simple', + queryParameters: { + 'appid': appId, + 'i': input, + // 'units': units, + // 'width': width, + // 'fontSize': fontSize, + // 'background': background, + // 'foreground': fontSize, + // 'layout': layout, + 'timeout': timeout, + }, + ); + if (response.statusCode == 501) { + return Exception(UnknownPrompt); + } + if (response.statusCode == 400) { + return Exception(MissingRequiredParameter); + } + if (response.data == 'Error 1: Invalid appid') { + return Exception(InvalidAppId); + } + return response.data; +} + +dynamic shortAnswers({ + required String appId, + required String input, + // String? units, + int? timeout = 5, +}) async { + Response response; + response = await dio.request('/v1/result', queryParameters: { + 'appid': appId, + 'i': input, + // 'units': units, + 'timeout': timeout, + }); + if (response.statusCode == 501) { + return Exception(UnknownPrompt); + } + if (response.statusCode == 400) { + return Exception(MissingRequiredParameter); + } + if (response.data == 'Error 1: Invalid appid') { + return Exception(InvalidAppId); + } + return response.data; +} + +dynamic spokenAnswers({ + required String appId, + required String input, + // String? units, + int? timeout = 5, +}) async { + Response response; + response = await dio.request('/v1/spoken', queryParameters: { + 'appid': appId, + 'i': input, + 'timeout': timeout, + }); + if (response.statusCode == 501) { + return Exception(UnknownPrompt); + } + if (response.statusCode == 400) { + return Exception(MissingRequiredParameter); + } + if (response.data == 'Error 1: Invalid appid') { + return Exception(InvalidAppId); + } + return response.data; +} + +dynamic fastQueryRecognizer({ + required String appId, + required String input, + String? mode, + String? output, +}) async { + Response response; + response = await dio.request('/queryrecognizer/query.jsp', queryParameters: { + 'appid': appId, + 'i': input, + // 'mode': mode, + // 'output: output, + }); + if (response.statusCode == 501) { + return Exception(UnknownPrompt); + } + if (response.statusCode == 400) { + return Exception(MissingRequiredParameter); + } + if (response.data == 'Error 1: Invalid appid') { + return Exception(InvalidAppId); + } + return response.data; +} + +dynamic fullResult({ + required String appId, + required String input, + String? format, + String? output, +}) async { + Response response; + response = await dio.request('/v2/query', queryParameters: { + 'appid': appId, + 'input': input, + // 'mode': mode, + // 'output: output, + }); + if (response.statusCode == 501) { + return Exception(UnknownPrompt); + } + if (response.statusCode == 400) { + return Exception(MissingRequiredParameter); + } + if (response.data == 'Error 1: Invalid appid') { + return Exception(InvalidAppId); + } + return response.data; +} diff --git a/lib/src/error.dart b/lib/src/error.dart new file mode 100644 index 0000000..b8d0f4e --- /dev/null +++ b/lib/src/error.dart @@ -0,0 +1,21 @@ + +/* + Thrown when the server rejects the API key + Commonly caused by expired/invalid/non-existent API key +*/ +final class InvalidAppId implements Exception { + final String message; + InvalidAppId(this.message); +} + +// Input cannot be interpreted by the API +final class UnknownPrompt implements Exception { + final String message; + UnknownPrompt(this.message); +} + +// API did not find the required input parameter. +final class MissingRequiredParameter implements Exception { + final String message; + MissingRequiredParameter(this.message); +} diff --git a/lib/wolframalpha.dart b/lib/wolframalpha.dart new file mode 100644 index 0000000..a616301 --- /dev/null +++ b/lib/wolframalpha.dart @@ -0,0 +1,5 @@ +library; + +export 'src/api.dart' show simple, shortAnswers, spokenAnswers; +export 'src/error.dart' + show InvalidAppId, UnknownPrompt, MissingRequiredParameter; diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..9e7ca85 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,22 @@ +name: wolframalpha_ai_dart +description: Dart client for interacting with WolframAlpha API, a engine for providing answers and knowledge. +version: 0.0.1 +repository: https://github.com/BoringExperiments/WolframAlpha_ai_dart + +environment: + sdk: ^3.3.0 + +platforms: + android: + ios: + linux: + macos: + web: + windows: + +dependencies: + dio: ^5.4.1 + +dev_dependencies: + lints: ^3.0.0 + test: ^1.24.0 diff --git a/test/api_test.dart b/test/api_test.dart new file mode 100644 index 0000000..4cf4145 --- /dev/null +++ b/test/api_test.dart @@ -0,0 +1,28 @@ +import 'package:wolframalpha_ai_dart/wolframalpha.dart'; +import 'package:test/test.dart'; + +void main() { + group('API', () { + test('Simple', () async { + final value = await simple( + appId: 'DEMO', + input: 'What is the price of gold?', + ); + expect(value.toString().isNotEmpty, true); + }); + test('Short Answers', () async { + final value = await shortAnswers( + appId: 'DEMO', + input: 'How many ounces are in a gallon?', + ); + expect(value.toString().isNotEmpty, true); + }); + test('Spoken Answers', () async { + final value = await spokenAnswers( + appId: 'DEMO', + input: 'Convert 42 mi to km', + ); + expect(value.toString().isNotEmpty, true); + }); + }); +}