-
-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(chat-models): Support OpenRouter API in ChatOpenAI wrapper (#292)
- Loading branch information
1 parent
57699b3
commit c6e7e5b
Showing
10 changed files
with
311 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
docs/modules/model_io/models/chat_models/integrations/open_router.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# OpenRouter | ||
|
||
[OpenRouter](https://openrouter.ai/) offers a unified OpenAI-compatible API for a broad range of models. | ||
|
||
You can also let users pay for their own models via their [OAuth PKCE](https://openrouter.ai/docs#oauth) flow. | ||
|
||
You can consume OpenRouter API using the `ChatOpenAI` wrapper in the same way you would use the OpenAI API. | ||
|
||
The only difference is that you need to change the base URL to `https://openrouter.ai/api/v1`: | ||
|
||
```dart | ||
final chatModel = ChatOpenAI( | ||
apiKey: openRouterApiKey, | ||
baseUrl: 'https://openrouter.ai/api/v1', | ||
defaultOptions: const ChatOpenAIOptions( | ||
model: 'mistralai/mistral-small', | ||
), | ||
); | ||
``` | ||
|
||
OpenRouter allows you to specify an optional `HTTP-Referer` header to identify your app and make it discoverable to users on openrouter.ai. You can also include an optional `X-Title` header to set or modify the title of your app. | ||
|
||
```dart | ||
final chatModel = ChatOpenAI( | ||
apiKey: openRouterApiKey, | ||
baseUrl: 'https://openrouter.ai/api/v1', | ||
headers: { | ||
'HTTP-Referer': 'com.myapp', | ||
'X-Title': 'OpenRouterTest', | ||
}, | ||
defaultOptions: const ChatOpenAIOptions( | ||
model: 'mistralai/mistral-small', | ||
), | ||
); | ||
``` | ||
|
||
## Invoke | ||
|
||
```dart | ||
final openRouterApiKey = Platform.environment['OPEN_ROUTER_API_KEY']; | ||
final promptTemplate = ChatPromptTemplate.fromTemplates(const [ | ||
( | ||
ChatMessageType.system, | ||
'You are a helpful assistant that translates {input_language} to {output_language}.', | ||
), | ||
(ChatMessageType.human, '{text}'), | ||
]); | ||
final chatModel = ChatOpenAI( | ||
apiKey: openRouterApiKey, | ||
baseUrl: 'https://openrouter.ai/api/v1', | ||
defaultOptions: const ChatOpenAIOptions( | ||
model: 'mistralai/mistral-small', | ||
), | ||
); | ||
final chain = promptTemplate | chatModel | const StringOutputParser(); | ||
final res = await chain.invoke({ | ||
'input_language': 'English', | ||
'output_language': 'French', | ||
'text': 'I love programming.', | ||
}); | ||
print(res); | ||
// -> 'J'aime la programmation.' | ||
``` | ||
|
||
## Stream | ||
|
||
```dart | ||
final openRouterApiKey = Platform.environment['OPEN_ROUTER_API_KEY']; | ||
final promptTemplate = ChatPromptTemplate.fromTemplates(const [ | ||
( | ||
ChatMessageType.system, | ||
'You are a helpful assistant that replies only with numbers ' | ||
'in order without any spaces or commas', | ||
), | ||
(ChatMessageType.human, 'List the numbers from 1 to {max_num}'), | ||
]); | ||
final chatModel = ChatOpenAI( | ||
apiKey: openRouterApiKey, | ||
baseUrl: 'https://openrouter.ai/api/v1', | ||
defaultOptions: const ChatOpenAIOptions( | ||
model: 'mistralai/mistral-small', | ||
), | ||
); | ||
final chain = promptTemplate.pipe(chatModel).pipe(const StringOutputParser()); | ||
final stream = chain.stream({'max_num': '9'}); | ||
await stream.forEach(print); | ||
// 123 | ||
// 456789 | ||
``` |
68 changes: 68 additions & 0 deletions
68
examples/docs_examples/bin/modules/model_io/models/chat_models/integrations/open_router.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// ignore_for_file: avoid_print | ||
import 'dart:io'; | ||
|
||
import 'package:langchain/langchain.dart'; | ||
import 'package:langchain_openai/langchain_openai.dart'; | ||
|
||
void main(final List<String> arguments) async { | ||
await _openRouter(); | ||
await _openRouterStreaming(); | ||
} | ||
|
||
Future<void> _openRouter() async { | ||
final openRouterApiKey = Platform.environment['OPEN_ROUTER_API_KEY']; | ||
|
||
final promptTemplate = ChatPromptTemplate.fromTemplates(const [ | ||
( | ||
ChatMessageType.system, | ||
'You are a helpful assistant that translates {input_language} to {output_language}.', | ||
), | ||
(ChatMessageType.human, '{text}'), | ||
]); | ||
|
||
final chatModel = ChatOpenAI( | ||
apiKey: openRouterApiKey, | ||
baseUrl: 'https://openrouter.ai/api/v1', | ||
defaultOptions: const ChatOpenAIOptions( | ||
model: 'mistralai/mistral-small', | ||
), | ||
); | ||
|
||
final chain = promptTemplate | chatModel | const StringOutputParser(); | ||
|
||
final res = await chain.invoke({ | ||
'input_language': 'English', | ||
'output_language': 'French', | ||
'text': 'I love programming.', | ||
}); | ||
print(res); | ||
// -> 'J'aime la programmation.' | ||
} | ||
|
||
Future<void> _openRouterStreaming() async { | ||
final openRouterApiKey = Platform.environment['OPEN_ROUTER_API_KEY']; | ||
|
||
final promptTemplate = ChatPromptTemplate.fromTemplates(const [ | ||
( | ||
ChatMessageType.system, | ||
'You are a helpful assistant that replies only with numbers ' | ||
'in order without any spaces or commas', | ||
), | ||
(ChatMessageType.human, 'List the numbers from 1 to {max_num}'), | ||
]); | ||
|
||
final chatModel = ChatOpenAI( | ||
apiKey: openRouterApiKey, | ||
baseUrl: 'https://openrouter.ai/api/v1', | ||
defaultOptions: const ChatOpenAIOptions( | ||
model: 'mistralai/mistral-small', | ||
), | ||
); | ||
|
||
final chain = promptTemplate.pipe(chatModel).pipe(const StringOutputParser()); | ||
|
||
final stream = chain.stream({'max_num': '9'}); | ||
await stream.forEach(print); | ||
// 123 | ||
// 456789 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
export 'chat_openai.dart'; | ||
export 'models/models.dart'; | ||
export 'openai.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
Oops, something went wrong.