-
-
Notifications
You must be signed in to change notification settings - Fork 11.6k
feat(neosantara): add Neosantara integration as OpenAI-compatible pro… #20641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0db990f
c5a4296
b80cf86
b68ba9a
e26c203
323fec1
526782b
583f645
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,201 @@ | ||
| import Tabs from '@theme/Tabs'; | ||
| import TabItem from '@theme/TabItem'; | ||
|
|
||
| # Neosantara | ||
|
|
||
| ## Overview | ||
|
|
||
| | Property | Details | | ||
| |-------|-------| | ||
| | Description | Neosantara is a unified LLM gateway designed for developers in Indonesia, providing a single OpenAI-compatible interface to multiple top-tier AI models (OpenAI, Anthropic, Gemini, etc.). | | ||
| | Provider Route on LiteLLM | `neosantara/` | | ||
| | Link to Provider Doc | [Neosantara Dashboard ↗](https://app.neosantara.xyz) | | ||
| | Base URL | `https://api.neosantara.xyz/v1` | | ||
| | Supported Operations | [`/chat/completions`](#sample-usage), [`/embeddings`](#embeddings) | | ||
|
|
||
| <br /> | ||
|
|
||
| ## What is Neosantara? | ||
|
|
||
| Neosantara is a unified gateway that lets developers: | ||
| - **Access Multiple LLM Providers**: Unified interface for OpenAI, Anthropic, Gemini, and more. | ||
| - **Optimized for Indonesia**: Designed specifically for the needs of developers in the region. | ||
| - **Unified Billing**: Pay-As-You-Go system with local payment support. | ||
| - **OpenAI Compatible**: Seamlessly drop into existing OpenAI-based workflows. | ||
|
|
||
| ## Required Variables | ||
|
|
||
| ```python showLineNumbers title="Environment Variables" | ||
| os.environ["NEOSANTARA_API_KEY"] = "your-neosantara-api-key" | ||
| ``` | ||
|
|
||
| Get your Neosantara API key from [app.neosantara.xyz](https://app.neosantara.xyz). | ||
|
|
||
| ## Usage - LiteLLM Python SDK | ||
|
|
||
| <Tabs> | ||
| <TabItem value="non-streaming" label="Non-streaming"> | ||
|
|
||
| ```python showLineNumbers title="Neosantara Non-streaming Completion" | ||
| import os | ||
| import litellm | ||
| from litellm import completion | ||
|
|
||
| os.environ["NEOSANTARA_API_KEY"] = "your-neosantara-api-key" | ||
|
|
||
| messages = [{"content": "What is the capital of Indonesia?", "role": "user"}] | ||
|
|
||
| # Neosantara call | ||
| response = completion( | ||
| model="neosantara/claude-3-haiku", | ||
| messages=messages | ||
| ) | ||
|
|
||
| print(response) | ||
| ``` | ||
|
|
||
| </TabItem> | ||
| <TabItem value="streaming" label="Streaming"> | ||
|
|
||
| ```python showLineNumbers title="Neosantara Streaming Completion" | ||
| import os | ||
| import litellm | ||
| from litellm import completion | ||
|
|
||
| os.environ["NEOSANTARA_API_KEY"] = "your-neosantara-api-key" | ||
|
|
||
| messages = [{"content": "Write a short poem about Jakarta", "role": "user"}] | ||
|
|
||
| # Neosantara call with streaming | ||
| response = completion( | ||
| model="neosantara/claude-3-haiku", | ||
| messages=messages, | ||
| stream=True | ||
| ) | ||
|
|
||
| for chunk in response: | ||
| print(chunk) | ||
| ``` | ||
|
|
||
| </TabItem> | ||
| <TabItem value="embeddings" label="Embeddings"> | ||
|
|
||
| ```python showLineNumbers title="Neosantara Embeddings" | ||
| import os | ||
| import litellm | ||
| from litellm import embedding | ||
|
|
||
| os.environ["NEOSANTARA_API_KEY"] = "your-neosantara-api-key" | ||
|
|
||
| # Neosantara call | ||
| response = embedding( | ||
| model="neosantara/nusa-embedding-0001", | ||
| input=["Hello, how are you?"] | ||
| ) | ||
|
|
||
| print(response) | ||
| ``` | ||
|
|
||
| </TabItem> | ||
| </Tabs> | ||
|
|
||
| ## Usage - LiteLLM Proxy Server | ||
|
|
||
| ### 1. Set Neosantara Models on `config.yaml` | ||
|
|
||
| ```yaml | ||
| model_list: | ||
| - model_name: neosantara-claude-3-haiku | ||
| litellm_params: | ||
| model: neosantara/claude-3-haiku | ||
| api_key: os.environ/NEOSANTARA_API_KEY | ||
| ``` | ||
|
|
||
| ### 2. Start Proxy | ||
|
|
||
| ```bash | ||
| litellm --config config.yaml | ||
| ``` | ||
|
|
||
| ### 3. Test it | ||
|
|
||
| <Tabs> | ||
| <TabItem value="Curl" label="Curl Request"> | ||
|
|
||
| ```shell | ||
| curl --location 'http://0.0.0.0:4000/chat/completions' \ | ||
| --header 'Content-Type: application/json' \ | ||
| --header 'Authorization: Bearer sk-1234' \ | ||
| --data ' { | ||
| "model": "neosantara-claude-3-haiku", | ||
| "messages": [ | ||
| { | ||
| "role": "user", | ||
| "content": "what llm are you" | ||
| } | ||
| ] | ||
| } | ||
| ' | ||
| ``` | ||
| </TabItem> | ||
| <TabItem value="openai" label="OpenAI v1.0.0+"> | ||
|
|
||
| ```python | ||
| import openai | ||
| client = openai.OpenAI( | ||
| api_key="anything", | ||
| base_url="http://0.0.0.0:4000" | ||
| ) | ||
|
|
||
| response = client.chat.completions.create( | ||
| model="neosantara-claude-3-haiku", | ||
| messages = [ | ||
| { | ||
| "role": "user", | ||
| "content": "this is a test request, write a short poem" | ||
| } | ||
| ] | ||
| ) | ||
|
|
||
| print(response) | ||
| ``` | ||
| </TabItem> | ||
| </Tabs> | ||
|
|
||
| ## Supported Models | ||
|
|
||
| We support a wide range of models optimized for the Indonesian context and high-performance tasks. | ||
|
|
||
| | Model Name | Model ID (for LiteLLM) | Provider | Description | | ||
| |------------|------------------------|----------|-------------| | ||
| | **Nusantara Base** | `neosantara/nusantara-base` | Gemini | Flagship balanced model | | ||
| | **Archipelago 70B** | `neosantara/archipelago-70b` | Llama 3.3 | Cultural context awareness | | ||
| | **Garda Beta Mini** | `neosantara/garda-beta-mini` | Groq/Paxsenix | Fast & efficient Indonesian understanding | | ||
| | **Claude 3 Haiku** | `neosantara/claude-3-haiku` | Bedrock | Near-instant responsiveness | | ||
| | **Claude 3 Sonnet** | `neosantara/claude-3-sonnet` | Bedrock | Balance of intelligence and speed | | ||
| | **Sahabat AI Llama v4** | `neosantara/sahabat-ai-llama-v4` | SahabatAI | Fine-tuned for Sahabat AI ecosystem | | ||
| | **Nusa Embedding 0001**| `neosantara/nusa-embedding-0001` | Embedding | Optimized for Indonesian search | | ||
|
|
||
| :::info | ||
| **Note:** You can use any model supported by Neosantara by adding the `neosantara/` prefix to the model name in your LiteLLM calls. | ||
| ::: | ||
|
|
||
| ## Supported OpenAI Parameters | ||
|
|
||
| Neosantara supports all standard OpenAI-compatible parameters: | ||
|
|
||
| | Parameter | Type | Description | | ||
| |-----------|------|-------------| | ||
| | `messages` | array | **Required**. Array of message objects with 'role' and 'content' | | ||
| | `model` | string | **Required**. Model ID (e.g., `claude-3-haiku`, `archipelago-70b`) | | ||
| | `stream` | boolean | Optional. Enable streaming responses | | ||
| | `temperature` | float | Optional. Sampling temperature | | ||
| | `top_p` | float | Optional. Nucleus sampling parameter | | ||
| | `max_tokens` | integer | Optional. Maximum tokens to generate | | ||
| | `tools` | array | Optional. List of available tools/functions | | ||
| | `tool_choice` | string/object | Optional. Control tool/function calling | | ||
|
|
||
| ## Additional Resources | ||
|
|
||
| - [Neosantara Dashboard](https://app.neosantara.xyz) | ||
| - [API Documentation](https://docs.neosantara.xyz) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -195,6 +195,21 @@ def get_llm_provider( # noqa: PLR0915 | |
| return model, custom_llm_provider, dynamic_api_key, api_base | ||
| # check if api base is a known openai compatible endpoint | ||
| if api_base: | ||
| if "api.neosantara.xyz/v1" in api_base: | ||
| custom_llm_provider = "neosantara" | ||
| dynamic_api_key = get_secret_str("NEOSANTARA_API_KEY") | ||
| if api_base is not None and not isinstance(api_base, str): | ||
| raise Exception( | ||
| "api base needs to be a string. api_base={}".format(api_base) | ||
| ) | ||
| if dynamic_api_key is not None and not isinstance(dynamic_api_key, str): | ||
| raise Exception( | ||
| "dynamic_api_key needs to be a string. dynamic_api_key={}".format( | ||
| dynamic_api_key | ||
| ) | ||
| ) | ||
| return model, custom_llm_provider, dynamic_api_key, api_base | ||
|
Comment on lines
+198
to
+211
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Auto-detection bypasses established pattern This hardcoded block is placed before the Neosantara should follow the same pattern:
This removes 14 lines of duplicated boilerplate and keeps the codebase consistent. Context Used: Rule from Why: This practice ensur... (source) |
||
|
|
||
| for endpoint in litellm.openai_compatible_endpoints: | ||
| if endpoint in api_base: | ||
| if endpoint == "api.perplexity.ai": | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4756,6 +4756,8 @@ def embedding( # noqa: PLR0915 | |||||||||
| or custom_llm_provider == "nvidia_nim" | ||||||||||
| or custom_llm_provider == "litellm_proxy" | ||||||||||
| or (model in litellm.open_ai_embedding_models and custom_llm_provider is None) | ||||||||||
| or custom_llm_provider in litellm.openai_compatible_providers | ||||||||||
| or JSONProviderRegistry.exists(custom_llm_provider) | ||||||||||
|
Comment on lines
+4759
to
+4760
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Catch-all breaks existing embedding providers These two new conditions (
With this change, these providers will fall into the generic OpenAI handler, which defaults To only add neosantara embedding support without breaking existing providers, the condition should be narrowed. For example:
Suggested change
Should instead be something like: Or, better yet, follow the existing pattern and add neosantara to the list at the top of this Context Used: Rule from Why: This practice ensur... (source) |
||||||||||
| ): | ||||||||||
| api_base = ( | ||||||||||
| api_base | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unsubstantiated token-array support claim
Adding
neosantaratoLITELLM_EMBEDDING_PROVIDERS_SUPPORTING_INPUT_ARRAY_OF_TOKENSmeans LiteLLM will allow callers to pass pre-tokenized integer arrays as embedding input. Only providers whose embedding endpoints actually accept token arrays (like OpenAI, Azure) should be in this list. There's no documentation or evidence that Neosantara'snusa-embedding-0001endpoint supports this — if it doesn't, this will cause silent failures or incorrect behavior at the provider level.