SDK
모든 OpenAI 또는 Anthropic SDK를 별도 설정 없이 사용할 수 있습니다.
Shannon은 OpenAI와 Anthropic의 전송 형식을 모두 지원하므로 두 곳의 공식 SDK를 그대로 사용할 수 있습니다. 클라이언트에서 기본 URL, API 키, 모델 id 세 값만 바꾸면 되며 나머지 코드는 그대로입니다.
설정할 것
| 설정 | OpenAI SDK | Anthropic SDK |
|---|---|---|
| 기본 URL | https://api.shannon-ai.com/v1 | https://api.shannon-ai.com |
| API 키 | Shannon 키입니다. SDK가 이를 Authorization: Bearer로 보냅니다. | Shannon 키입니다. SDK가 이를 x-api-key로 보냅니다. |
| 모델 | 공개된 모델 id입니다. 예: shannon-3. | 공개된 모델 id입니다. 예: shannon-1.6-lite. |
| 연결되는 엔드포인트 | /v1/chat/completions, /v1/responses, /v1/models | /v1/messages, /v1/messages/count_tokens |
| 환경 변수 | OPENAI_API_KEY와 OPENAI_BASE_URL이며, 값을 전달하지 않으면 Python 및 JavaScript SDK가 읽습니다. | ANTHROPIC_API_KEY와 ANTHROPIC_BASE_URL이며, 값을 전달하지 않으면 Python 및 TypeScript SDK가 읽습니다. |
두 기본 URL은 /v1만큼 다릅니다. OpenAI SDK는 기본 URL에 /chat/completions를 붙이고, Anthropic SDK는 /v1/messages를 붙입니다. Shannon이 공개하지 않은 모델 이름은 400과 unknown model로 응답합니다. 모델 및 가격
키는 Keys & usage 페이지에 있습니다. Keys & usage
OpenAI SDK
공식 OpenAI SDK는 POST /v1/chat/completions와 POST /v1/responses를 호출합니다. 각 샘플은 사용자 메시지 하나를 보내고 답변을 출력합니다.
# pip install openai
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com/v1",
)
response = client.chat.completions.create(
model="shannon-3",
messages=[{"role": "user", "content": "Hello, Shannon!"}],
)
print(response.choices[0].message.content) // npm install openai
import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com/v1",
});
const response = await client.chat.completions.create({
model: "shannon-3",
messages: [{ role: "user", content: "Hello, Shannon!" }],
});
console.log(response.choices[0].message.content); // go get github.com/openai/openai-go/v3
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/option"
)
func main() {
client := openai.NewClient(
option.WithAPIKey("YOUR_API_KEY"),
option.WithBaseURL("https://api.shannon-ai.com/v1/"),
)
completion, err := client.Chat.Completions.New(context.TODO(), openai.ChatCompletionNewParams{
Model: "shannon-3",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.UserMessage("Hello, Shannon!"),
},
})
if err != nil {
panic(err)
}
fmt.Println(completion.Choices[0].Message.Content)
} // Gradle: implementation("com.openai:openai-java:<version>")
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
OpenAIClient client = OpenAIOkHttpClient.builder()
.apiKey("YOUR_API_KEY")
.baseUrl("https://api.shannon-ai.com/v1")
.build();
ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model("shannon-3")
.addUserMessage("Hello, Shannon!")
.build();
ChatCompletion completion = client.chat().completions().create(params);
completion.choices().get(0).message().content().ifPresent(System.out::println); // dotnet add package OpenAI
using System.ClientModel;
using OpenAI;
using OpenAI.Chat;
ChatClient client = new(
model: "shannon-3",
credential: new ApiKeyCredential("YOUR_API_KEY"),
options: new OpenAIClientOptions()
{
Endpoint = new Uri("https://api.shannon-ai.com/v1")
});
ChatCompletion completion = client.CompleteChat("Hello, Shannon!");
Console.WriteLine(completion.Content[0].Text); | 언어 | 설치 | 기본 URL 옵션 | 소스 |
|---|---|---|---|
| Python | pip install openai | base_url | openai/openai-python |
| JavaScript / TypeScript | npm install openai | baseURL | openai/openai-node |
| Go | go get github.com/openai/openai-go/v3 | option.WithBaseURL | openai/openai-go |
| Java | com.openai:openai-java | baseUrl | openai/openai-java |
| .NET | dotnet add package OpenAI | OpenAIClientOptions.Endpoint | openai/openai-dotnet |
두 엔드포인트의 모든 필드는 각각의 페이지에 설명되어 있습니다. Chat Completions Responses API
Anthropic SDK
공식 Anthropic SDK는 POST /v1/messages를 호출합니다. 모든 호출에서 max_tokens가 필요하므로, 샘플은 이를 적용하는 shannon-1.6-lite를 사용합니다. 각 샘플은 답변의 텍스트 블록을 출력합니다.
# pip install anthropic
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com",
)
message = client.messages.create(
model="shannon-1.6-lite",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Shannon!"}],
)
for block in message.content:
if block.type == "text":
print(block.text) // npm install @anthropic-ai/sdk
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com",
});
const message = await client.messages.create({
model: "shannon-1.6-lite",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello, Shannon!" }],
});
for (const block of message.content) {
if (block.type === "text") console.log(block.text);
} // go get github.com/anthropics/anthropic-sdk-go
package main
import (
"context"
"fmt"
"github.com/anthropics/anthropic-sdk-go"
"github.com/anthropics/anthropic-sdk-go/option"
)
func main() {
client := anthropic.NewClient(
option.WithAPIKey("YOUR_API_KEY"),
option.WithBaseURL("https://api.shannon-ai.com/"),
)
message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
Model: "shannon-1.6-lite",
MaxTokens: 1024,
Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock("Hello, Shannon!")),
},
})
if err != nil {
panic(err)
}
for _, block := range message.Content {
if block.Type == "text" {
fmt.Println(block.Text)
}
}
} // Gradle: implementation("com.anthropic:anthropic-java:<version>")
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
AnthropicClient client = AnthropicOkHttpClient.builder()
.apiKey("YOUR_API_KEY")
.baseUrl("https://api.shannon-ai.com")
.build();
MessageCreateParams params = MessageCreateParams.builder()
.model("shannon-1.6-lite")
.maxTokens(1024L)
.addUserMessage("Hello, Shannon!")
.build();
Message message = client.messages().create(params);
message.content().stream()
.flatMap(block -> block.text().stream())
.forEach(text -> System.out.println(text.text())); | 언어 | 설치 | 기본 URL 옵션 | 소스 |
|---|---|---|---|
| Python | pip install anthropic | base_url | anthropics/anthropic-sdk-python |
| TypeScript | npm install @anthropic-ai/sdk | baseURL | anthropics/anthropic-sdk-typescript |
| Go | go get github.com/anthropics/anthropic-sdk-go | option.WithBaseURL | anthropics/anthropic-sdk-go |
| Java | com.anthropic:anthropic-java | baseUrl | anthropics/anthropic-sdk-java |
Messages 형식과 차이점은 Anthropic compatibility 페이지에 있습니다. Anthropic 형식
SDK가 의존할 수 있는 것
- API가 사용하지 않는 요청 필드는 허용됩니다. API가 아는 필드를 잘못된 타입으로 보내면
422로 응답합니다. - SDK가 추가하는 버전 및 베타 헤더(
anthropic-version,anthropic-beta,openai-beta)는 허용됩니다. 어느 것도 필수는 아닙니다. - 응답의
model은 공개된 id이므로 그대로 다시 보낼 수 있습니다. /v1/messages에서는 응답이thinking블록으로 시작할 수 있습니다. 첫 블록을 쓰지 말고 type이text인 블록을 읽으세요.- 스트리밍은 SDK 자체의 스트림 헬퍼로 작동합니다. 사용량은 모든 스트림의 끝에 도착합니다.
- 모든 응답에는
x-request-id헤더가 있습니다. 직접x-request-id를 보내면 같은 값이 돌아옵니다.
커뮤니티 SDK
다른 작성자가 OpenAI API용으로 만든 클라이언트도 같은 방식으로 작동합니다. 클라이언트에 /v1이 붙은 기본 URL, 키, Shannon 모델 id를 지정하세요. 이들은 Shannon이 아니라 각 작성자가 관리합니다.
| 언어 | 설치 | 클라이언트 |
|---|---|---|
| Go | go get github.com/sashabaranov/go-openai | sashabaranov/go-openai |
| Ruby | gem install ruby-openai | alexrudall/ruby-openai |
| PHP | composer require openai-php/client | openai-php/client |
| Rust | cargo add async-openai | 64bit/async-openai |
SDK 없이
SDK가 꼭 필요하지는 않습니다. JSON을 보낼 수 있는 HTTP 클라이언트라면 무엇이든 작동합니다.
- JSON 본문과
Content-Type: application/json헤더를 가진POST입니다. 헤더가 없으면 요청은415로 응답합니다. - 키는
Authorization: Bearer <key>또는x-api-key: <key>에 넣습니다. 두 방식 모두 모든 엔드포인트에서 작동합니다. - 본문은 최대 32 MiB입니다.
"stream": true이면 응답은 server-sent event 스트림(text/event-stream)입니다. 한 줄씩 읽고 버퍼링하지 마세요.- 오류는 HTTP 상태와 함께
error.type과error.message가 있는 JSON 본문입니다.
curl https://api.shannon-ai.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "shannon-3",
"messages": [{"role": "user", "content": "Hello, Shannon!"}]
}' import requests
response = requests.post(
"https://api.shannon-ai.com/v1/chat/completions",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"model": "shannon-3",
"messages": [{"role": "user", "content": "Hello, Shannon!"}],
},
)
response.raise_for_status()
print(response.json()["choices"][0]["message"]["content"]) const response = await fetch("https://api.shannon-ai.com/v1/chat/completions", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "shannon-3",
messages: [{ role: "user", content: "Hello, Shannon!" }],
}),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
console.log(data.choices[0].message.content);