Skip to content

Commit

Permalink
feat: Allow to update OpenAI key without having to recreate the wrapp…
Browse files Browse the repository at this point in the history
…er (#246)
  • Loading branch information
davidmigloz committed Nov 23, 2023
1 parent 3e15925 commit 05739bd
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 9 deletions.
6 changes: 6 additions & 0 deletions packages/langchain_openai/lib/src/agents/tools/dall_e.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ final class OpenAIDallETool extends Tool<OpenAIDallEToolOptions> {
/// The default options to use when calling the DALL-E tool.
final OpenAIDallEToolOptions defaultOptions;

/// Set or replace the API key.
set apiKey(final String value) => _client.apiKey = value;

/// Get the API key.
String get apiKey => _client.apiKey;

@override
FutureOr<String> runInternalString(
final String toolInput, {
Expand Down
64 changes: 61 additions & 3 deletions packages/langchain_openai/lib/src/chat_models/openai.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,69 @@ import 'models/models.dart';
///
/// Example:
/// ```dart
/// final chat = ChatOpenAI(apiKey: '...', temperature: 1);
/// final chatModel = ChatOpenAI(apiKey: '...');
/// final messages = [
/// ChatMessage.system('You are a helpful assistant that translates English to French.'),
/// ChatMessage.humanText('I love programming.')
/// ChatMessage.humanText('I love programming.'),
/// ];
/// final res = await chat(messages);
/// final prompt = PromptValue.chat(messages);
/// final res = await llm.invoke(prompt);
/// ```
///
/// - [Completions guide](https://platform.openai.com/docs/guides/gpt/chat-completions-api)
/// - [Completions API docs](https://platform.openai.com/docs/api-reference/chat)
///
/// ### Call options
///
/// You can configure the parameters that will be used when calling the
/// chat completions API in several ways:
///
/// **Default options:**
///
/// Use the [defaultOptions] parameter to set the default options. These
/// options will be used unless you override them when generating completions.
///
/// ```dart
/// final chatModel = ChatOpenAI(
/// apiKey: openaiApiKey,
/// defaultOptions: const ChatOpenAIOptions(
/// temperature: 0.9,
/// maxTokens: 100,
/// ),
/// );
/// ```
///
/// **Call options:**
///
/// You can override the default options when invoking the model:
///
/// ```dart
/// final res = await chatModel.invoke(
/// prompt,
/// options: const ChatOpenAIOptions(seed: 9999),
/// );
/// ```
///
/// **Bind:**
///
/// You can also change the options in a [Runnable] pipeline using the bind
/// method.
///
/// In this example, we are using two totally different models for each
/// question:
///
/// ```dart
/// final llm = OpenAI(apiKey: openaiApiKey,);
/// const outputParser = StringOutputParser();
/// final prompt1 = PromptTemplate.fromTemplate('How are you {name}?');
/// final prompt2 = PromptTemplate.fromTemplate('How old are you {name}?');
/// final chain = Runnable.fromMap({
/// 'q1': prompt1 | llm.bind(const OpenAIOptions(model: 'gpt-3.5-turbo-instruct')) | outputParser,
/// 'q2': prompt2| llm.bind(const OpenAIOptions(model: 'text-davinci-003')) | outputParser,
/// });
/// final res = await chain.invoke({'name': 'David'});
/// ```
///
/// ### Authentication
///
/// The OpenAI API uses API keys for authentication. Visit your
Expand Down Expand Up @@ -169,6 +221,12 @@ class ChatOpenAI extends BaseChatModel<ChatOpenAIOptions> {
/// https://github.com/mvitlov/tiktoken/blob/master/lib/tiktoken.dart
final String? encoding;

/// Set or replace the API key.
set apiKey(final String value) => _client.apiKey = value;

/// Get the API key.
String get apiKey => _client.apiKey;

@override
String get modelType => 'openai-chat';

Expand Down
6 changes: 6 additions & 0 deletions packages/langchain_openai/lib/src/embeddings/openai.dart
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ class OpenAIEmbeddings implements Embeddings {
/// Ref: https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids
final String? user;

/// Set or replace the API key.
set apiKey(final String value) => _client.apiKey = value;

/// Get the API key.
String get apiKey => _client.apiKey;

@override
Future<List<List<double>>> embedDocuments(
final List<Document> documents,
Expand Down
67 changes: 61 additions & 6 deletions packages/langchain_openai/lib/src/llms/openai.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,69 @@ import 'package:tiktoken/tiktoken.dart';
import 'models/mappers.dart';
import 'models/models.dart';

/// Wrapper around OpenAI Completions API.
/// Wrapper around [OpenAI Completions API](https://platform.openai.com/docs/api-reference/completions).
///
/// Example:
/// ```dart
/// final llm = OpenAI(
/// apiKey: openaiApiKey,
/// defaultOptions: const OpenAIOptions(temperature: 1),
/// );
/// final res = await llm('Tell me a joke');
/// final llm = OpenAI(apiKey: '...');
/// final prompt = PromptValue.string('Tell me a joke');
/// final res = await llm.invoke(prompt);
/// ```
///
/// - [Completions guide](https://platform.openai.com/docs/guides/gpt/completions-api)
/// - [Completions API docs](https://platform.openai.com/docs/api-reference/completions)
///
/// ### Call options
///
/// You can configure the parameters that will be used when calling the
/// completions API in several ways:
///
/// **Default options:**
///
/// Use the [defaultOptions] parameter to set the default options. These
/// options will be used unless you override them when generating completions.
///
/// ```dart
/// final llm = OpenAI(
/// apiKey: openaiApiKey,
/// defaultOptions: const OpenAIOptions(
/// temperature: 0.9,
/// maxTokens: 100,
/// ),
/// );
/// ```
///
/// **Call options:**
///
/// You can override the default options when invoking the model:
///
/// ```dart
/// final res = await llm.invoke(
/// prompt,
/// options: const OpenAIOptions(seed: 9999),
/// );
/// ```
///
/// **Bind:**
///
/// You can also change the options in a [Runnable] pipeline using the bind
/// method.
///
/// In this example, we are using two totally different models for each
/// question:
///
/// ```dart
/// final chatModel = ChatOpenAI(apiKey: openaiApiKey,);
/// const outputParser = StringOutputParser();
/// final prompt1 = PromptTemplate.fromTemplate('How are you {name}?');
/// final prompt2 = PromptTemplate.fromTemplate('How old are you {name}?');
/// final chain = Runnable.fromMap({
/// 'q1': prompt1 | chatModel.bind(const ChatOpenAIOptions(model: 'gpt-4')) | outputParser,
/// 'q2': prompt2| chatModel.bind(const ChatOpenAIOptions(model: 'gpt-3.5-turbo')) | outputParser,
/// });
/// final res = await chain.invoke({'name': 'David'});
/// ```
///
/// ### Authentication
///
/// The OpenAI API uses API keys for authentication. Visit your
Expand Down Expand Up @@ -168,6 +217,12 @@ class OpenAI extends BaseLLM<OpenAIOptions> {
/// https://github.com/mvitlov/tiktoken/blob/master/lib/tiktoken.dart
final String? encoding;

/// Set or replace the API key.
set apiKey(final String value) => _client.apiKey = value;

/// Get the API key.
String get apiKey => _client.apiKey;

@override
String get modelType => 'openai';

Expand Down
6 changes: 6 additions & 0 deletions packages/openai_dart/lib/src/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ class OpenAIClient extends g.OpenAIClient {
client: client ?? createDefaultHttpClient(),
);

/// Set or replace the API key.
set apiKey(final String value) => bearerToken = value;

/// Get the API key.
String get apiKey => bearerToken;

// ------------------------------------------
// METHOD: createCompletionStream
// ------------------------------------------
Expand Down

0 comments on commit 05739bd

Please sign in to comment.