Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
oriventi committed May 30, 2024
0 parents commit 5601796
Show file tree
Hide file tree
Showing 20 changed files with 1,389 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 1.0.0

- Initial version.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
A sample command-line application with an entrypoint in `bin/`, library code
in `lib/`, and example unit test in `test/`.
30 changes: 30 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -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
33 changes: 33 additions & 0 deletions bin/groq_sdk.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:groq_sdk/groq_sdk.dart';
import 'package:groq_sdk/models/groq.dart';
import 'package:groq_sdk/models/groq_chat.dart';
import 'package:groq_sdk/models/groq_llm_model.dart';

void main(List<String> arguments) async {
final groq = Groq('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');
groq.canUseModel(llama3_8b).then((model) {
print(model);
});

final chat = groq.startNewChat(llama3_8b,
settings: GroqChatSettings.defaults().copyWith(choicesCount: 2));

chat.stream.listen((event) {
if (event is RequestChatEvent) {
print('Request sent...');
print(event.message.content);
} else if (event is ResponseChatEvent) {
print('Received response: ${event.response.choices.first.message}');
}
});

final (_, usage) = await chat.sendMessage('Explain LLMs to me please.');

print("Total tokens used: ${usage.totalTokens}");
print("Total time taken: ${usage.totalTime}");
print("Rate limit information: ${chat.rateLimitInfo.toString()}");
print("-------------------");
await Future.delayed(Duration(seconds: 2));
await chat.sendMessage('What is the difference between LLM and GPT-3?');
await Future.delayed(Duration(seconds: 5));
}
10 changes: 10 additions & 0 deletions lib/groq_sdk.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export 'models/chat_event.dart';
export 'models/groq_chat.dart';
export 'models/groq_conversation_item.dart';
export 'models/groq_exceptions.dart';
export 'models/groq_llm_model.dart';
export 'models/groq_message.dart';
export 'models/groq_rate_limit_information.dart';
export 'models/groq_response.dart';
export 'models/groq_usage.dart';
export 'models/groq.dart';
52 changes: 52 additions & 0 deletions lib/models/chat_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import 'package:groq_sdk/models/groq_message.dart';
import 'package:groq_sdk/models/groq_response.dart';
import 'package:groq_sdk/models/groq_usage.dart';

///Is the type received by the chat stream \
///It can be a request or a response \
///The request just contains the message \
///The response contains the message and the resource usage \
///Example:
///```dart
///chat.stream.listen((event) {
/// if (event is RequestChatEvent) {
/// print(event.message.message);
/// } else if (event is ResponseChatEvent) {
/// print(event.response.choices.first.message);
/// print(event.usage.totalTokens);
/// }
sealed class ChatEvent {
const ChatEvent();
}

///Is the type received by the chat stream \
///It contains the message to be sent to the chat \
///Example:
///```dart
///chat.stream.listen((event) {
/// if (event is RequestChatEvent) {
/// print(event.message.message);
/// }
///}
/// ```
class RequestChatEvent extends ChatEvent {
final GroqMessage message;
RequestChatEvent(this.message);
}

///Is the type received by the chat stream \
///It contains the response from the chat and the resource usage \
///Example:
///```dart
///chat.stream.listen((event) {
/// if (event is ResponseChatEvent) {
/// print(event.response.choices.first.message);
/// print(event.usage.totalTokens);
/// }
///}
///```
class ResponseChatEvent extends ChatEvent {
final GroqResponse response;
final GroqUsage usage;
ResponseChatEvent(this.response, this.usage);
}
77 changes: 77 additions & 0 deletions lib/models/groq.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import 'package:groq_sdk/models/groq_api.dart';
import 'package:groq_sdk/models/groq_chat.dart';
import 'package:groq_sdk/models/groq_llm_model.dart';

class Groq {
///The API key to use the Groq API \
///Obtain it from the Groq website: \
///https://console.groq.com/keys
String apiKey;

///Creates a new Groq instance \
///[apiKey] is the API key to use the Groq API \
///You can communicate with the Groq API via a Chat instance \
///Example:
///```dart
///final groq = Groq('EXAMPLE_API_KEY');
///final chat = groq.startNewChat(llama3_8b); //use a model id, provided by Groq
///final (response, resourceUsage) = await chat.sendMessage('YOUR_MESSAGE');
///```
Groq(this.apiKey);

///Returns the model metadata from groq with the given model id
Future<GroqLLMModel> getModel(String modelId) async {
return await GroqApi.getModel(modelId, apiKey);
}

///Returns a list of all model metadatas available in Groq
Future<List<GroqLLMModel>> listModels() async {
return await GroqApi.listModels(apiKey);
}

///Returns whether the model with the given model id can be used \
///It returns true if the model is currently active and false otherwise \
///Example:
///```dart
///if (await groq.canUseModel(llama3_8b)) {
/// final chat = groq.startNewChat(llama3_8b);
///}
///```
Future<bool> canUseModel(String modelId) async {
try {
final model = await getModel(modelId);
return model.isCurrentlyActive;
} catch (e) {
return false;
}
}

///Returns a new chat instance with the given model id \
///`modelId` is the model id to use for the chat \
///`settings` are the chat settings, defaults to GroqChatSettings.defaults() \
///`customApiKey` is the API key to use for the chat, defaults to the Groq instance API key \
///Example:
///```dart
/// final chat = groq.startNewChat(llama3_8b);
/// final (response, resourceUsage) = await chat.sendMessage('YOUR_MESSAGE');
/// ```
/// Or use the chat as a stream:
/// ```dart
/// chat.stream.listen((event) {
/// if (event is RequestChatEvent) {
/// print(event.request.message.message);
/// } else if (event is ResponseChatEvent) {
/// print(event.response.choices.first.message);
/// print(event.usage.totalTokens);
/// }
/// });
/// ```
GroqChat startNewChat(
String modelId, {
GroqChatSettings settings = const GroqChatSettings.defaults(),
String? customApiKey,
}) {
final specificApiKey = customApiKey ?? apiKey;
return GroqChat(modelId, specificApiKey, settings);
}
}
81 changes: 81 additions & 0 deletions lib/models/groq_api.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import 'dart:convert';

import 'package:groq_sdk/models/groq_chat.dart';
import 'package:groq_sdk/models/groq_conversation_item.dart';
import 'package:groq_sdk/models/groq_exceptions.dart';
import 'package:groq_sdk/models/groq_llm_model.dart';
import 'package:groq_sdk/models/groq_message.dart';
import 'package:groq_sdk/models/groq_rate_limit_information.dart';
import 'package:groq_sdk/models/groq_response.dart';
import 'package:groq_sdk/models/groq_usage.dart';
import 'package:groq_sdk/utils/auth_http.dart';

class GroqApi {
static const String _chatCompletionUrl =
'https://api.groq.com/openai/v1/chat/completions';
static const String _getModelBaseUrl =
'https://api.groq.com/openai/v1/models';

static Future<GroqLLMModel> getModel(String modelId, String apiKey) async {
final response =
await AuthHttp.get(url: '$_getModelBaseUrl/$modelId', apiKey: apiKey);
if (response.statusCode == 200) {
return GroqLLMModel.fromJson(json.decode(response.body));
} else {
throw GroqException.fromResponse(response);
}
}

static Future<List<GroqLLMModel>> listModels(String apiKey) async {
final response = await AuthHttp.get(url: _getModelBaseUrl, apiKey: apiKey);
if (response.statusCode == 200) {
final Map<String, dynamic> jsonData = json.decode(response.body);
final List<dynamic> jsonList = jsonData['data'] as List<dynamic>;
return jsonList.map((json) => GroqLLMModel.fromJson(json)).toList();
} else {
throw GroqException.fromResponse(response);
}
}

static Future<(GroqResponse, GroqUsage, GroqRateLimitInformation)>
getNewChatCompletion({
required String apiKey,
required GroqMessage prompt,
required GroqChat chat,
}) async {
final Map<String, dynamic> jsonMap = {};
List<Map<String, dynamic>> messages = [];
List<GroqConversationItem> allMessages = chat.allMessages;
if (chat.allMessages.length > chat.settings.maxConversationalMemoryLength) {
allMessages.removeRange(
0, allMessages.length - chat.settings.maxConversationalMemoryLength);
}
for (final message in allMessages) {
messages.add(message.request.toJson());
messages.add(message.response!.choices.first.messageData.toJson());
}
messages.add(prompt.toJson());
jsonMap['messages'] = messages;
jsonMap['model'] = chat.model;
jsonMap.addAll(chat.settings.toJson());
final response = await AuthHttp.post(
url: _chatCompletionUrl, apiKey: apiKey, body: jsonMap);
//Rate Limit information
final rateLimitInfo =
GroqRateLimitInformation.fromHeaders(response.headers);
if (response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
final GroqResponse groqResponse = GroqResponse.fromJson(jsonData);
final GroqUsage groqUsage = GroqUsage.fromJson(jsonData["usage"]);
return (groqResponse, groqUsage, rateLimitInfo);
} else if (response.statusCode == 429) {
throw GroqRateLimitException(
retryAfter: Duration(
seconds: int.tryParse(response.headers['retry-after'] ?? '0') ?? 0,
),
);
} else {
throw GroqException.fromResponse(response);
}
}
}
Loading

0 comments on commit 5601796

Please sign in to comment.