Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ For more details about component implementations, please refer to the [Eino ecos
- **callback handlers**: official callback handlers implementing Eino's CallbackHandler interface, such as [Langfuse tracing](https://langfuse.com/docs/tracing) callback.
- **DevOps tools**: IDE plugin for Eino that enables visualized debugging, UI based graph editing and more. For more details, please refer to the [Eino Dev tooling documentation.](https://www.cloudwego.io/zh/docs/eino/core_modules/devops/)

## Atlas Cloud

**[Atlas Cloud](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=eino-ext)** is a full-modal AI inference platform that gives developers a single AI API to access video generation, image generation, and LLM APIs. Instead of managing multiple vendor integrations, you connect once and get unified access to 300+ curated models across all modalities.

Check out Atlas Cloud's new coding plan promotion for more budget-friendly API access: [https://www.atlascloud.ai/console/coding-plan](https://www.atlascloud.ai/console/coding-plan)

## Security

If you discover a potential security issue in this project, or think you may
Expand Down
88 changes: 88 additions & 0 deletions components/model/atlascloud/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Atlas Cloud ChatModel

An Atlas Cloud ChatModel implementation for [Eino](https://github.com/cloudwego/eino).
It wraps the OpenAI-compatible model client and defaults the LLM endpoint to `https://api.atlascloud.ai/v1`.

## Features

- Implements `github.com/cloudwego/eino/components/model.ToolCallingChatModel`
- Uses Atlas Cloud's OpenAI-compatible chat completions API
- Supports streaming responses
- Supports tool calling
- Supports request/response modifiers from the OpenAI-compatible client

## Installation

```bash
go get github.com/cloudwego/eino-ext/components/model/atlascloud@latest
```

## Quick Start

```go
package main

import (
"context"
"fmt"
"log"
"os"

"github.com/cloudwego/eino/schema"
"github.com/cloudwego/eino-ext/components/model/atlascloud"
)

func main() {
ctx := context.Background()

chatModel, err := atlascloud.NewChatModel(ctx, &atlascloud.ChatModelConfig{
APIKey: os.Getenv("ATLASCLOUD_API_KEY"),
Model: os.Getenv("ATLASCLOUD_MODEL"), // e.g. deepseek-ai/DeepSeek-V3-0324
// BaseURL is optional. Default: https://api.atlascloud.ai/v1
})
if err != nil {
log.Fatalf("NewChatModel failed: %v", err)
}

resp, err := chatModel.Generate(ctx, []*schema.Message{
schema.UserMessage("Explain Eino in one sentence."),
})
if err != nil {
log.Fatalf("Generate failed: %v", err)
}

fmt.Println(resp.Content)
}
```

## Configuration

`atlascloud.ChatModelConfig` is an alias of `openai.ChatModelConfig`, so you can use the same OpenAI-compatible fields:

- `APIKey`: required
- `Model`: required
- `BaseURL`: optional, defaults to `https://api.atlascloud.ai/v1`
- `Timeout`, `HTTPClient`
- `Temperature`, `TopP`, `Stop`
- `MaxCompletionTokens`, `ResponseFormat`, `ReasoningEffort`
- `ExtraFields`, request/response modifiers, and other OpenAI-compatible options

## Notes

- Atlas Cloud's chat API is OpenAI-compatible.
- The `/v1` suffix is required in the base URL.
- Model names should use Atlas Cloud's model library IDs, such as `deepseek-ai/DeepSeek-V3-0324`.

## Validated Atlas LLM Pool

Recommended validated Atlas Cloud model IDs for `ATLASCLOUD_MODEL`:

- `deepseek-ai/DeepSeek-V3-0324`, `deepseek-ai/deepseek-r1-0528`, `moonshotai/Kimi-K2-Instruct`, `Qwen/Qwen3-Coder`, `Qwen/Qwen3-235B-A22B-Instruct-2507`, `deepseek-ai/DeepSeek-V3.1`, `moonshotai/Kimi-K2-Instruct-0905`, `Qwen/Qwen3-Next-80B-A3B-Instruct`, `Qwen/Qwen3-Next-80B-A3B-Thinking`, `Qwen/Qwen3-30B-A3B-Instruct-2507`
- `deepseek-ai/DeepSeek-V3.1-Terminus`, `deepseek-ai/DeepSeek-V3.2-Exp`, `zai-org/GLM-4.6`, `MiniMaxAI/MiniMax-M2`, `Qwen/Qwen3-VL-235B-A22B-Instruct`, `moonshotai/Kimi-K2-Thinking`, `google/gemini-2.5-flash`, `google/gemini-2.5-flash-lite`, `openai/gpt-5.1`, `openai/gpt-5.1-chat`
- `openai/gpt-4o`, `openai/gpt-4o-mini`, `openai/gpt-4.1`, `openai/gpt-4.1-mini`, `openai/gpt-4.1-nano`, `openai/o1`, `openai/o3`, `openai/o3-mini`, `openai/o4-mini`, `anthropic/claude-sonnet-4.5-20250929`
- `deepseek-ai/deepseek-v3.2`, `openai/gpt-5`, `openai/gpt-5-chat`, `openai/gpt-5-mini`, `openai/gpt-5-nano`, `openai/gpt-5.2`, `openai/gpt-5.2-chat`, `google/gemini-2.5-pro`, `anthropic/claude-opus-4.5-20251101`, `google/gemini-3-flash-preview`
- `zai-org/glm-4.7`, `minimaxai/minimax-m2.1`, `google/gemini-2.0-flash`, `qwen/qwen3-8b`, `qwen/qwen3-235b-a22b-thinking-2507`, `qwen/qwen3-vl-235b-a22b-thinking`, `qwen/qwen3-30b-a3b`, `qwen/qwen3-30b-a3b-thinking-2507`, `deepseek-ai/deepseek-ocr`, `xai/grok-4-0709`

## Example

See [examples/basic](./examples/basic/).
88 changes: 88 additions & 0 deletions components/model/atlascloud/README_zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Atlas Cloud ChatModel

这是一个面向 [Eino](https://github.com/cloudwego/eino) 的 Atlas Cloud ChatModel 实现。
它基于 OpenAI 兼容客户端封装,并将 LLM 默认地址设为 `https://api.atlascloud.ai/v1`。

## 特性

- 实现 `github.com/cloudwego/eino/components/model.ToolCallingChatModel`
- 使用 Atlas Cloud 的 OpenAI 兼容 Chat Completions API
- 支持流式输出
- 支持工具调用
- 支持复用 OpenAI 兼容客户端的请求/响应扩展能力

## 安装

```bash
go get github.com/cloudwego/eino-ext/components/model/atlascloud@latest
```

## 快速开始

```go
package main

import (
"context"
"fmt"
"log"
"os"

"github.com/cloudwego/eino/schema"
"github.com/cloudwego/eino-ext/components/model/atlascloud"
)

func main() {
ctx := context.Background()

chatModel, err := atlascloud.NewChatModel(ctx, &atlascloud.ChatModelConfig{
APIKey: os.Getenv("ATLASCLOUD_API_KEY"),
Model: os.Getenv("ATLASCLOUD_MODEL"), // 例如 deepseek-ai/DeepSeek-V3-0324
// BaseURL 可选,默认是 https://api.atlascloud.ai/v1
})
if err != nil {
log.Fatalf("NewChatModel failed: %v", err)
}

resp, err := chatModel.Generate(ctx, []*schema.Message{
schema.UserMessage("请用一句话介绍 Eino。"),
})
if err != nil {
log.Fatalf("Generate failed: %v", err)
}

fmt.Println(resp.Content)
}
```

## 配置说明

`atlascloud.ChatModelConfig` 是 `openai.ChatModelConfig` 的别名,因此可直接使用同一套 OpenAI 兼容配置字段:

- `APIKey`:必填
- `Model`:必填
- `BaseURL`:可选,默认 `https://api.atlascloud.ai/v1`
- `Timeout`、`HTTPClient`
- `Temperature`、`TopP`、`Stop`
- `MaxCompletionTokens`、`ResponseFormat`、`ReasoningEffort`
- `ExtraFields`、请求/响应 modifier 等 OpenAI 兼容能力

## 说明

- Atlas Cloud 的 Chat API 完全兼容 OpenAI。
- `BaseURL` 必须带上 `/v1` 后缀。
- 模型名请使用 Atlas Cloud 模型库中的模型 ID,例如 `deepseek-ai/DeepSeek-V3-0324`。

## 已验证 Atlas LLM 模型池

推荐作为 `ATLASCLOUD_MODEL` 使用的已验证 Atlas Cloud 模型 ID:

- `deepseek-ai/DeepSeek-V3-0324`, `deepseek-ai/deepseek-r1-0528`, `moonshotai/Kimi-K2-Instruct`, `Qwen/Qwen3-Coder`, `Qwen/Qwen3-235B-A22B-Instruct-2507`, `deepseek-ai/DeepSeek-V3.1`, `moonshotai/Kimi-K2-Instruct-0905`, `Qwen/Qwen3-Next-80B-A3B-Instruct`, `Qwen/Qwen3-Next-80B-A3B-Thinking`, `Qwen/Qwen3-30B-A3B-Instruct-2507`
- `deepseek-ai/DeepSeek-V3.1-Terminus`, `deepseek-ai/DeepSeek-V3.2-Exp`, `zai-org/GLM-4.6`, `MiniMaxAI/MiniMax-M2`, `Qwen/Qwen3-VL-235B-A22B-Instruct`, `moonshotai/Kimi-K2-Thinking`, `google/gemini-2.5-flash`, `google/gemini-2.5-flash-lite`, `openai/gpt-5.1`, `openai/gpt-5.1-chat`
- `openai/gpt-4o`, `openai/gpt-4o-mini`, `openai/gpt-4.1`, `openai/gpt-4.1-mini`, `openai/gpt-4.1-nano`, `openai/o1`, `openai/o3`, `openai/o3-mini`, `openai/o4-mini`, `anthropic/claude-sonnet-4.5-20250929`
- `deepseek-ai/deepseek-v3.2`, `openai/gpt-5`, `openai/gpt-5-chat`, `openai/gpt-5-mini`, `openai/gpt-5-nano`, `openai/gpt-5.2`, `openai/gpt-5.2-chat`, `google/gemini-2.5-pro`, `anthropic/claude-opus-4.5-20251101`, `google/gemini-3-flash-preview`
- `zai-org/glm-4.7`, `minimaxai/minimax-m2.1`, `google/gemini-2.0-flash`, `qwen/qwen3-8b`, `qwen/qwen3-235b-a22b-thinking-2507`, `qwen/qwen3-vl-235b-a22b-thinking`, `qwen/qwen3-30b-a3b`, `qwen/qwen3-30b-a3b-thinking-2507`, `deepseek-ai/deepseek-ocr`, `xai/grok-4-0709`

## 示例

参考 [examples/basic](./examples/basic/)。
180 changes: 180 additions & 0 deletions components/model/atlascloud/atlascloud.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* Copyright 2026 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package atlascloud

import (
"context"
"fmt"

"github.com/cloudwego/eino/components/model"
"github.com/cloudwego/eino/schema"

modelopenai "github.com/cloudwego/eino-ext/components/model/openai"
)

const (
// DefaultBaseURL is Atlas Cloud's OpenAI-compatible LLM endpoint.
DefaultBaseURL = "https://api.atlascloud.ai/v1"

ChatCompletionResponseFormatTypeJSONObject = modelopenai.ChatCompletionResponseFormatTypeJSONObject
ChatCompletionResponseFormatTypeJSONSchema = modelopenai.ChatCompletionResponseFormatTypeJSONSchema
ChatCompletionResponseFormatTypeText = modelopenai.ChatCompletionResponseFormatTypeText
)

type (
ChatCompletionResponseFormat = modelopenai.ChatCompletionResponseFormat
ChatCompletionResponseFormatJSONSchema = modelopenai.ChatCompletionResponseFormatJSONSchema
ChatModelConfig = modelopenai.ChatModelConfig
RequestPayloadModifier = modelopenai.RequestPayloadModifier
ResponseMessageModifier = modelopenai.ResponseMessageModifier
ResponseChunkMessageModifier = modelopenai.ResponseChunkMessageModifier
ReasoningEffortLevel = modelopenai.ReasoningEffortLevel
Modality = modelopenai.Modality
Audio = modelopenai.Audio
AudioFormat = modelopenai.AudioFormat
AudioVoice = modelopenai.AudioVoice
)

const (
ReasoningEffortLevelLow = modelopenai.ReasoningEffortLevelLow
ReasoningEffortLevelMedium = modelopenai.ReasoningEffortLevelMedium
ReasoningEffortLevelHigh = modelopenai.ReasoningEffortLevelHigh

TextModality = modelopenai.TextModality
AudioModality = modelopenai.AudioModality

AudioFormatMp3 = modelopenai.AudioFormatMp3
AudioFormatWav = modelopenai.AudioFormatWav
AudioFormatFlac = modelopenai.AudioFormatFlac
AudioFormatOpus = modelopenai.AudioFormatOpus
AudioFormatPcm16 = modelopenai.AudioFormatPcm16

AudioVoiceAlloy = modelopenai.AudioVoiceAlloy
AudioVoiceAsh = modelopenai.AudioVoiceAsh
AudioVoiceBallad = modelopenai.AudioVoiceBallad
AudioVoiceCoral = modelopenai.AudioVoiceCoral
AudioVoiceEcho = modelopenai.AudioVoiceEcho
AudioVoiceFable = modelopenai.AudioVoiceFable
AudioVoiceNova = modelopenai.AudioVoiceNova
AudioVoiceOnyx = modelopenai.AudioVoiceOnyx
AudioVoiceSage = modelopenai.AudioVoiceSage
AudioVoiceShimmer = modelopenai.AudioVoiceShimmer
)

// ChatModel wraps the OpenAI-compatible ChatModel with Atlas Cloud defaults.
type ChatModel struct {
inner *modelopenai.ChatModel
}

var _ model.ToolCallingChatModel = (*ChatModel)(nil)

// NewChatModel creates an Atlas Cloud chat model using Atlas's OpenAI-compatible endpoint by default.
func NewChatModel(ctx context.Context, config *ChatModelConfig) (*ChatModel, error) {
if config == nil {
return nil, fmt.Errorf("config cannot be nil")
}

nc := *config
if nc.BaseURL == "" {
nc.BaseURL = DefaultBaseURL
}

inner, err := modelopenai.NewChatModel(ctx, &nc)
if err != nil {
return nil, err
}

return &ChatModel{inner: inner}, nil
}

// Generate delegates to the underlying OpenAI-compatible model.
func (cm *ChatModel) Generate(ctx context.Context, in []*schema.Message, opts ...model.Option) (*schema.Message, error) {
return cm.inner.Generate(ctx, in, opts...)
}

// Stream delegates to the underlying OpenAI-compatible streaming API.
func (cm *ChatModel) Stream(ctx context.Context, in []*schema.Message, opts ...model.Option) (*schema.StreamReader[*schema.Message], error) {
return cm.inner.Stream(ctx, in, opts...)
}

// WithTools binds tools and returns another Atlas Cloud chat model.
func (cm *ChatModel) WithTools(tools []*schema.ToolInfo) (model.ToolCallingChatModel, error) {
toolModel, err := cm.inner.WithTools(tools)
if err != nil {
return nil, err
}

inner, ok := toolModel.(*modelopenai.ChatModel)
if !ok {
return nil, fmt.Errorf("unexpected tool model type %T", toolModel)
}

return &ChatModel{inner: inner}, nil
}

// BindTools binds tools on the current model instance.
func (cm *ChatModel) BindTools(tools []*schema.ToolInfo) error {
return cm.inner.BindTools(tools)
}

// BindForcedTools binds tools and forces the model to call one of them.
func (cm *ChatModel) BindForcedTools(tools []*schema.ToolInfo) error {
return cm.inner.BindForcedTools(tools)
}

func (cm *ChatModel) GetType() string {
return "AtlasCloud"
}

func (cm *ChatModel) IsCallbacksEnabled() bool {
return cm.inner.IsCallbacksEnabled()
}

// WithExtraFields sets additional top-level request fields.
func WithExtraFields(extraFields map[string]any) model.Option {
return modelopenai.WithExtraFields(extraFields)
}

// WithExtraHeader sets additional request headers.
func WithExtraHeader(header map[string]string) model.Option {
return modelopenai.WithExtraHeader(header)
}

// WithReasoningEffort overrides the request-level reasoning effort.
func WithReasoningEffort(effort ReasoningEffortLevel) model.Option {
return modelopenai.WithReasoningEffort(effort)
}

// WithMaxCompletionTokens overrides the request-level max completion tokens.
func WithMaxCompletionTokens(maxCompletionTokens int) model.Option {
return modelopenai.WithMaxCompletionTokens(maxCompletionTokens)
}

// WithRequestPayloadModifier customizes the serialized request body before sending.
func WithRequestPayloadModifier(modifier RequestPayloadModifier) model.Option {
return modelopenai.WithRequestPayloadModifier(modifier)
}

// WithResponseMessageModifier customizes non-streaming responses using the raw body.
func WithResponseMessageModifier(m ResponseMessageModifier) model.Option {
return modelopenai.WithResponseMessageModifier(m)
}

// WithResponseChunkMessageModifier customizes streaming responses using each raw chunk body.
func WithResponseChunkMessageModifier(m ResponseChunkMessageModifier) model.Option {
return modelopenai.WithResponseChunkMessageModifier(m)
}
Loading
Loading