Bosphorus

← Bilgi bankası

Evren model rehberi: sohbet, embedding, rerank, karar, OCR

Her Evren model türü ne işe yarar, hangi uygulama hangisini gösterir, kişisel API anahtarınızı nasıl alırsınız: her tür için denenmiş curl ve Python örnekleri.

APIEvrenModellerGeliştiricilerÜrün üzerinde doğrulandığı tarih:

Evren anahtarınıza ulaşmanın üç yolu

Bir EV/ modeline giden aynı istek: aimo'dan, VS Code eklentisinden ve kendi uygulamanızdan. Değişen tek şey, sizin kim olduğunuzu nasıl kanıtladığıdır.

aimo, sohbet çalışma alanı

aimo her turu sizin adınıza imzalar; böylece ortak bağlantısı yine de kim olduğunuzu taşır.

  1. Sizaimo'da şirket hesabınızla oturum açar ve bir EV/ modeli seçersiniz.İletilen mesajınız
  2. aimoİstemciaimo kendi servis anahtarını ve sizin için imzalanmış kısa ömürlü bir belirteç ekler.İletilen servis anahtarı + imzalı belirteciniz
  3. Ağ geçidiAğ geçidi imzayı doğrular ve isteğin sizden geldiğini bilir. Kişisel limitleriniz uygulanır.İletilen kim olduğunuz
  4. KasanızEvren anahtarınız yalnızca bu çağrı için okunur.İletilen Evren anahtarınız
  5. EvrenEvren sohbette yanıt verir. Kullanım sizin adınıza kaydedilir.

Evren anahtarı yoksa: aimo nedeni bir sohbet mesajı olarak, My variables bağlantısıyla gösterir; sohbet açık kalır.

VS Code için aimo

Eklenti, oturum açtığınızda üretilen kendi kişisel anahtarını tutar.

  1. SizBir kez, cihaz koduyla oturum açarsınız.İletilen isteğiniz
  2. VS CodeİstemciEklenti, VS Code'un gizli deposunda tuttuğu kişisel anahtarınızı gönderir.İletilen kişisel anahtarınız
  3. Ağ geçidiAğ geçidi anahtarı size bağlar. Limitleriniz uygulanır.İletilen kim olduğunuz
  4. KasanızEvren anahtarınız yalnızca bu çağrı için okunur.İletilen Evren anahtarınız
  5. EvrenEvren düzenleyicide yanıt verir. Kullanım sizin adınıza kaydedilir.

Evren anahtarı yoksa: Sohbet paneli ağ geçidinin gerekçesini gösterir ve Select model düğmesini sunar.

Uygulamanız, herkesin kendi anahtarıyla

Herkes bir kez kişisel anahtar alır; uygulamanız da onu o kişinin istekleriyle gönderir.

  1. SizKişi, oturum açarak bir kez kişisel anahtar alır.İletilen kişinin isteği
  2. UygulamanızİstemciUygulamanız o kişinin anahtarını Bearer olarak gönderir.İletilen kişinin kişisel anahtarı
  3. Ağ geçidiAğ geçidi anahtarı o kişiye bağlar. Onun limitleri uygulanır.İletilen kişinin kimliği
  4. KasanızO kişinin Evren anahtarı yalnızca bu çağrı için okunur.İletilen kişinin Evren anahtarı
  5. EvrenEvren uygulamanıza yanıt verir. Kullanım o kişinin adına kaydedilir.

Evren anahtarı yoksa: Gerekçesiyle birlikte HTTP 503. Onu gösterin ve kişiyi My variables sayfasına yönlendirin.

Uygulamanız, tek bir ekip anahtarıyla

Ekip anahtarı bir kişiyi değil bir ekibi temsil eder; okunacak bir Evren anahtarı yoktur.

  1. Sizİnsanlar uygulamanızı kullanır.İletilen bir istek
  2. UygulamanızİstemciUygulamanız herkes için aynı ekip anahtarını gönderir.İletilen ekip anahtarı
  3. Ağ geçidi503Ağ geçidi anahtarın arkasında bir kişi bulamaz ve 503 döner.
  4. KasanızHiçbir kasa okunmaz.Hiç ulaşılmaz
  5. EvrenEvren hiç çağrılmaz.Hiç ulaşılmaz

Bunun yerine ne olur: Her EV/ çağrısı 503 döner: this request carries no user identity. Kendi anahtarınızı gerektirmeyen modeller ekip anahtarıyla çalışmaya devam eder.

Neler farklı
aimoVS CodeAPI, kişisel anahtarAPI, ekip anahtarı
Nasıl oturum açılırTarayıcıda şirket hesabıylaBir kez, cihaz koduylaKişi başına bir kez, cihaz koduylaHiç açılmaz
İstek ne taşıraimo'nun anahtarı + imzalı belirtecinizKişisel anahtarınızO kişinin anahtarıTek bir ekip anahtarı
Ağ geçidi kimi görürSiziSiziO kişiyiKimseyi
Kullanılan Evren anahtarıSizinkiSizinkiO kişininkiYok: 503

Her durumda Evren anahtarını bir kez, My variables sayfasına kaydedersiniz ve hiçbir istemci onu tutmaz. aimo, oturum açmış kişi adına imza atabilir, çünkü platform ona bu konuda güvenir; dışarıdaki bir uygulamaya bu yetki verilmez, bu yüzden uygulama her kişinin kendi anahtarını gönderir.

Platform yalnızca sohbet modelleri sunmuyor. Bazı modeller metni vektöre çevirir, bazıları belgeleri bir soruya göre puanlar, bazıları türü belli sorulara olasılıklarla yanıt verir, bazıları da görüntüdeki ya da sesteki metni çıkarır. Bu makale model türlerini, hangi uygulamanın hangisini gösterdiğini ve her türü kendi kodunuzdan nasıl çağıracağınızı anlatıyor. Bütün türleri kapsadıkları için örneklerin hepsinde Evren modelleri (EV/…) kullanılıyor. Her örnek 10 Ekim 2026’da canlı bir kurulumda çalıştırıldı; aktarılan yanıtlar o gün alınanlardır.

Model türleri

GET /v1/models yanıtındaki her kaydın bir type alanı vardır. Bu alan, modele hangi uç noktanın yanıt verdiğini söyler. Bir model yalnızca kendi uç noktasında çalışır: sohbet uç noktasına gönderilen bir rerank modeli, doğru uç noktayı adıyla söyleyen bir 400 alır.

Tür Ne yapar Tipik kullanım Uç nokta Evren modelleri
llm Metin yazar, talimat izler, araç çağırır Asistanlar, ajanlar, özetler, kod POST /v1/chat/completions EV/deepseek-v4-flash, EV/glm-5.3, EV/gemma-4-31b, EV/qwen3-vl-30b (görüntü okur), EV/auto ve diğerleri
guard Bir mesajı güvenli ya da güvensiz diye sınıflandırır, kategorileriyle Bir LLM çağrısından önce ya da sonra denetim POST /v1/chat/completions EV/qwen3-guard-4b
embedding Metni 4096 sayılık bir vektöre çevirir Anlamsal arama, bilgi getirme, kümeleme, tekrarları bulma POST /v1/embeddings EV/qwen3-embedding-8b
rerank Her belgenin bir soruyla ne kadar ilgili olduğunu puanlar Arama sonuçlarını LLM’e gitmeden önce sıralamak POST /v1/rerank EV/qwen3-reranker-8b
decision Bir metin hakkındaki türü belli sorulara düz metin yerine olasılıklarla yanıt verir Talep yönlendirme, önceliklendirme, evet/hayır kontrolleri POST /api/alpha/decisions EV/clef (metin ve görüntü), EV/laya
ocr Görüntüdeki metni olduğu gibi döndürür Fişler, taranmış formlar, ekran görüntüleri POST /v1/ocr EV/dots-ocr, EV/deepseek-ocr-2
transcription Konuşmayı metne çevirir Toplantı notları, sesli giriş POST /v1/audio/transcriptions EV/qwen3-asr-1.7b

Diğer sağlayıcılar da aynı türleri kullanır; vlm, şirket içi havuzda görüntü de okuyabilen bir sohbet modelidir. Sohbet modelleri, sağlayıcı bildiriyorsa capabilities alanını da taşır: vision, tools ve reasoning. Diğer türlerde bu alan yoktur.

Model nasıl seçilir

Nerede Ne sunar
aimo, sohbet penceresi Yalnızca sohbet modelleri. Diğer türler orada gizlenir, çünkü onlarla sohbet başarısız olur.
VS Code için aimo 1.1.4 ve sonrası Select Model listesinde ve varsayılan seçimde yalnızca sohbet modelleri.
Ajan çalışma alanı Ajan düzenleyicide yalnızca sohbet modelleri. Model yönlendiricisi, her istek için model seçerken karar modellerini kullanabilir.
Kendi kodunuz Anahtarınızla GET /v1/models okuyun ve type alanına göre seçin. Model profiliniz listeyi daraltabilir; yalnızca çağırabileceğiniz modelleri görürsünüz.

Model kimlikleri bir sağlayıcı önekiyle gelir. EV/ Evren demektir: Türkiye’de barındırılır, kendi Evren anahtarınızla çalışır ve ücreti kendi Evren krediniz ödenir. Öneksiz kimlik de çalışır.

curl -s $GW/v1/models -H "Authorization: Bearer $BOSPHORUS_KEY" \
  | jq -r '.data[] | select(.id | startswith("EV/")) | "\(.type)\t\(.id)"' | sort

Bu yazının hazırlandığı gün 16 Evren modeli listelendi: iki decision, bir embedding, bir guard, sekiz llm, iki ocr, bir rerank ve bir transcription.

Bölüm A: anahtarlarınız, bir kez

Evren modelleri herkesin kendi Evren anahtarıyla çalışır. Bu anahtarı bir istekte asla göndermezsiniz: My variables sayfasında saklarsınız ve ağ geçidi, isteğin kimliğini bildirdiği kişi için onu okur. Bu yüzden kodunuzun sizi tanıtan bir kişisel platform anahtarına, gpk_…, ihtiyacı vardır. Örneklerde bu anahtarın adı $BOSPHORUS_KEY. Bir ekip ya da servis anahtarı bir kişiyi tanıtmaz; Evren modelleri onu 503 ile geri çevirir.

A1. Evren anahtarınızı kaydedin

  1. Evren portalında bir Evren LLM anahtarı oluşturun. evren_llm_ ile başlar. evren_mdl_ ile başlayan anahtar yanlış türdür ve kabul edilmez.
  2. Konsolda My variables sayfasını açın, Evren keys bölümünü bulun, LLM anahtarını yapıştırıp Save düğmesine basın. Kaydetmek, Evren’in kullanım koşullarını sizin adınıza kabul eder. Platform anahtarı (evren_plt_…) isteğe bağlıdır ve yalnızca kredi bakiyenizi gösterir.

A2. Kişisel API anahtarınızı alın

Aynı My variables sayfasında, en üstteki My API key kartında Create my API key düğmesine basın. Anahtar bir Copy düğmesiyle birlikte görünür; kabuğunuza BOSPHORUS_KEY olarak yükleyin. Bir kopyası kendi kasanızda saklanır: Show key aynı anahtarı daha sonra yeniden gösterir, Replace de gerektiğinde yenisini verir.

Bunun yerine terminalden

Hesabınız konsolu açamıyorsa anahtarı şirket hesabınızla oturum açarak üretin. curl ve jq gerekir; Windows’ta WSL ya da Git Bash kullanın. Microsoft Entra ID ile oturum açan bir kurulumda:

GW=https://ai.corp.example
CFG=$(curl -s $GW/api/identity/config)
TENANT=$(echo "$CFG" | jq -r .entra.tenantId)
CLIENT=$(echo "$CFG" | jq -r .entra.clientId)
SCOPE=$(echo "$CFG" | jq -r .entra.scope)
DA=https://login.microsoftonline.com/$TENANT/oauth2/v2.0/devicecode
TE=https://login.microsoftonline.com/$TENANT/oauth2/v2.0/token
DC=$(curl -s $DA -d client_id=$CLIENT --data-urlencode "scope=$SCOPE")
echo "$DC" | jq -r .message

Yazdırdığı adresi açın, kodu girin ve oturum açın. Sonra aynı terminalde:

TOKEN=$(curl -s $TE -d grant_type=urn:ietf:params:oauth:grant-type:device_code \
  -d client_id=$CLIENT -d device_code=$(echo "$DC" | jq -r .device_code) | jq -r .access_token)
curl -s -X POST "$GW/api/identity/token?client=api" -H "Authorization: Bearer $TOKEN" | jq -r .key.key

Son komut anahtarınızı bir kez yazdırır ve kopyasını saklamaz. Bir parola yöneticisinde saklayın ve kabuğunuza BOSPHORUS_KEY olarak yükleyin. Kendi OpenID Connect sağlayıcısıyla oturum açan bir kurulumda adımlar aynıdır, yalnızca adresler değişir; API’yi kendi anahtarlarınızla çağırmak makalesi ikisini de gösteriyor.

Anahtarı hangi yoldan almış olursanız olun, sizi tanıttığını ve Evren anahtarınızın kayıtlı olduğunu kontrol edin:

export GW=https://ai.corp.example
export BOSPHORUS_KEY=gpk_...
curl -s $GW/api/identity/me -H "Authorization: Bearer $BOSPHORUS_KEY" | jq -r .user.email
curl -s $GW/api/identity/evren-key -H "Authorization: Bearer $BOSPHORUS_KEY" | jq -r .llm.status

İlk satır e-posta adresinizi, ikincisi active yazar. İlk satırda null görürseniz bir ekip anahtarı kullanıyorsunuz demektir.

A3. Anahtarı kaybettiniz ya da yardım mı gerekiyor?

Durumunuz Ne yapmalı
Hiç anahtarınız olmadı My variables sayfasında Create my API key düğmesine basın. Birkaç saniye sürer.
Vardı, kaybettiniz My variables sayfasında oluşturduysanız orada Show key düğmesine basın. Terminalden alınan anahtar yalnızca üretildiği anda gösterilir: terminal adımlarını yeniden çalıştırıp son komuta &rotate=true ekleyin; eski anahtar geçersiz olur, yenisi yazdırılır. VS Code için aimo’nun tuttuğu anahtar gibi diğer anahtarlarınız etkilenmez.
Sızmış olabilir Hemen yenileyin: My variables sayfasında Replace, terminal anahtarı için &rotate=true. Anahtarı ele geçiren herkes sizin adınıza, sizin Evren kredinizle model çağırabilir.
Yalnızca tek bir çağrı denemek istiyorsunuz Oturum açma belirteci, $TOKEN, en az bir kez kişisel anahtar ürettiyseniz yaklaşık bir saat boyunca Bearer olarak çalışır.
Oturum açma reddediliyor ya da kontrol null yazıyor Platform yöneticinize başvurun. Hesabınızın oturum açabildiğini ve ekip anahtarı kullanmadığınızı kontrol edebilir. Sizin yerinize kişisel anahtar üretemez: anahtar yalnızca sizin oturum açmanızdan üretilir ve sizi tanıtmasını sağlayan da budur.
Kişiye değil, ortak bir servise anahtar gerekiyor Yöneticiden Teams & Keys üzerinde bir ekip ya da servis anahtarı isteyin. Böyle bir anahtar EV/ modellerini kullanamaz, çünkü arkasında Evren anahtarı okunabilecek bir kişi yoktur.

Bölüm B: örnekler

Python örnekleri, karşılığı olan çağrılarda OpenAI SDK’sını, tanımadığı üç uç nokta için de requests kütüphanesini kullanır: rerank, karar ve OCR. Önce GW ve BOSPHORUS_KEY değişkenlerini A2’deki gibi ayarlayın.

B1. Sohbet

Herhangi bir OpenAI SDK’sı, yalnızca adres ve anahtar değiştirilerek çalışır. Bazı Evren sohbet modelleri yanıt vermeden önce düşünür ve max_tokens değerini düşünme ile yanıt arasında paylaşır; küçük bir max_tokens boş bir yanıt döndürebilir. Bu değeri hiç vermeyin ya da geniş tutun.

curl -s $GW/v1/chat/completions -H "Authorization: Bearer $BOSPHORUS_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"model":"EV/deepseek-v4-flash","messages":[{"role":"user","content":"Merhaba"}]}' \
  | jq -r '.choices[0].message.content'

Bir denemede Merhaba! Size nasıl yardımcı olabilirim? yanıtını verdi. Aynı çağrı Python’dan, ardından akış hâlinde bir çağrı:

import os
from openai import OpenAI

client = OpenAI(base_url=os.environ["GW"] + "/v1", api_key=os.environ["BOSPHORUS_KEY"])

reply = client.chat.completions.create(
    model="EV/deepseek-v4-flash",
    messages=[{"role": "user", "content": "Merhaba"}],
)
print(reply.choices[0].message.content)

for chunk in client.chat.completions.create(
    model="EV/glm-5.3", stream=True,
    messages=[{"role": "user", "content": "Count to five."}],
):
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

B2. Guard

EV/qwen3-guard-4b sohbet etmez. Kontrol edilecek mesajı gönderirsiniz, bir karar ve kategorilerle yanıt verir. Bir ajan kullanıcı girdisine göre davranmadan önce ya da bir yanıtı göstermeden önce kullanın.

curl -s $GW/v1/chat/completions -H "Authorization: Bearer $BOSPHORUS_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"model":"EV/qwen3-guard-4b","messages":[{"role":"user","content":"What is the weather in Izmir?"}]}' \
  | jq -r '.choices[0].message.content'

İki satırda Safety: Safe ve Categories: None yanıtını verdi. Silah yapımıyla ilgili bir soru ise Safety: Unsafe ve Categories: Violent döndürdü. Küçük bir ayrıştırıcı:

def guard(client, text):
    out = client.chat.completions.create(
        model="EV/qwen3-guard-4b",
        messages=[{"role": "user", "content": text}],
    ).choices[0].message.content
    fields = dict(line.split(": ", 1) for line in out.splitlines() if ": " in line)
    safe = fields.get("Safety") == "Safe"
    cats = [] if fields.get("Categories") in (None, "None") else fields["Categories"].split(", ")
    return safe, cats

B3. Embedding

Embedding bir metni anlamına göre konumlandırır: aynı konudaki metinler birbirine yakın düşer. Belgelerinizi bir kez vektöre çevirip saklayın, sonra her soruyu da çevirip karşılaştırın. Birden çok metni tek çağrıda çevirmek için input alanına bir liste verin.

curl -s $GW/v1/embeddings -H "Authorization: Bearer $BOSPHORUS_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"model":"EV/qwen3-embedding-8b","input":"Merhaba dünya"}' \
  | jq '.data[0].embedding | length'

4096 yazdırdı. Üç metni karşılaştırmak:

import math

def embed(client, texts):
    r = client.embeddings.create(model="EV/qwen3-embedding-8b", input=texts)
    return [d.embedding for d in r.data]

def cosine(a, b):
    dot = sum(x * y for x, y in zip(a, b))
    return dot / (math.sqrt(sum(x * x for x in a)) * math.sqrt(sum(y * y for y in b)))

q, related, unrelated = embed(client, [
    "How do I reset my VPN password?",
    "Steps to change the password of your VPN account",
    "The canteen serves lentil soup on Fridays",
])
print(round(cosine(q, related), 3), round(cosine(q, unrelated), 3))

0.856 0.262 yazdırdı: ilgili çift çok daha yüksek puan alıyor. Her dizinde tek bir embedding modeli kullanın, çünkü farklı modellerin vektörleri karşılaştırılamaz.

B4. Rerank

Rerank modeli soruyu ve her belgeyi birlikte okuyup ilgiyi puanlar. Embedding karşılaştırmasından daha isabetli ama daha yavaştır, bu yüzden kısa bir listede kullanın: embedding ile 20-50 aday bulun, onları yeniden sıralayın ve en iyi birkaçını LLM’e verin. Sonuçlar puana göre sıralı gelir; index, gönderdiğiniz listedeki sırayı gösterir.

curl -s $GW/v1/rerank -H "Authorization: Bearer $BOSPHORUS_KEY" \
  -H 'Content-Type: application/json' -d '{
    "model": "EV/qwen3-reranker-8b",
    "query": "What is the capital of France?",
    "documents": ["Bananas are yellow.", "Paris is the capital of France.", "Berlin is in Germany."]
  }' | jq -c '.results[] | {index, relevance_score}'

1 numaralı belgeyi 0.551 ile ilk sıraya koydu, ardından 2 numarayı 0.002 ve 0 numarayı 0.0004 ile. Yanıt her belgeyi de geri verir ve usage.prompt_tokens değerini bildirir. Model, soru ve belge için toplam 4K token okur; uzun belgeleri parçalara bölün. Python’dan:

import os, requests

GW, KEY = os.environ["GW"], os.environ["BOSPHORUS_KEY"]

def rerank(query, documents, top=3):
    r = requests.post(f"{GW}/v1/rerank", timeout=60,
                      headers={"Authorization": f"Bearer {KEY}"},
                      json={"model": "EV/qwen3-reranker-8b", "query": query, "documents": documents})
    r.raise_for_status()
    return [(documents[x["index"]], x["relevance_score"]) for x in r.json()["results"][:top]]

B5. Karar

Karar modeli bir e-posta, talep ya da JSON kaydı gibi bir state okur ve adı konmuş, türü belli questions sorularına düz metin yerine olasılıklarla yanıt verir. Yanıt hızlıdır ve biçimi sabittir; bu da yönlendirme ve önceliklendirme için uygundur. choice sorusu criteria alır: etiketlerden oluşan bir liste ya da etiket ve açıklamadan oluşan bir nesne. Diğer türler score ve noul (evet/hayır olasılığı); bu makalede choice denendi. EV/clef ayrıca images alanında data URL olarak en fazla dört görüntü kabul eder.

curl -s $GW/api/alpha/decisions -H "Authorization: Bearer $BOSPHORUS_KEY" \
  -H 'Content-Type: application/json' -d '{
    "model": "EV/clef",
    "state": "Hi, I want my money back for the broken kettle.",
    "questions": {
      "intent": {
        "type": "choice",
        "instructions": "What does the customer want?",
        "criteria": {"refund": "money back", "shipping": "where is my package", "other": "anything else"}
      }
    }
  }' | jq .answers

"choice": "refund" yanıtını 0.99 güvenle ve her etiket için bir olasılıkla verdi. criteria yerine options göndermek a choice question takes ‘criteria’ as a dict of label -> description, or a list of labels hatasıyla reddedilir. Python’dan:

import os, requests

GW, KEY = os.environ["GW"], os.environ["BOSPHORUS_KEY"]

def route_ticket(text):
    r = requests.post(f"{GW}/api/alpha/decisions", timeout=60,
                      headers={"Authorization": f"Bearer {KEY}"},
                      json={
                          "model": "EV/clef",
                          "state": text,
                          "questions": {"intent": {
                              "type": "choice",
                              "instructions": "What does the customer want?",
                              "criteria": {"refund": "money back",
                                           "shipping": "where is my package",
                                           "other": "anything else"},
                          }},
                      })
    r.raise_for_status()
    a = r.json()["answers"]["intent"]
    return a["choice"], a["confidence"]

B6. OCR

Görüntüyü image alanında data URL olarak gönderin. Yanıt, görüntüdeki metni olduğu gibi text alanında verir. Ağ geçidi yalnızca JSON kabul eder, bu yüzden dosyayı kendiniz kodlayın. Denetim kaydı görüntünün türünü ve boyutunu tutar, görüntünün kendisini asla.

IMG=$(base64 < invoice.png | tr -d '\n')
jq -n --arg img "data:image/png;base64,$IMG" '{model: "EV/dots-ocr", image: $img}' \
  | curl -s $GW/v1/ocr -H "Authorization: Bearer $BOSPHORUS_KEY" \
      -H 'Content-Type: application/json' -d @- | jq -r .text

Bir fatura satırının 640 x 160 piksellik görüntüsü için Invoice 4711 ve Total: 128.50 EUR döndürdü. Python’dan:

import base64, mimetypes, os, requests

GW, KEY = os.environ["GW"], os.environ["BOSPHORUS_KEY"]

def ocr(path, model="EV/dots-ocr"):
    mime = mimetypes.guess_type(path)[0] or "image/png"
    data = base64.b64encode(open(path, "rb").read()).decode()
    r = requests.post(f"{GW}/v1/ocr", timeout=120,
                      headers={"Authorization": f"Bearer {KEY}"},
                      json={"model": model, "image": f"data:{mime};base64,{data}"})
    r.raise_for_status()
    return r.json()["text"]

Küçük görüntülerde çıktıyı kontrol edin. Aynı metin 420 x 90 piksele ve iki renge küçültüldüğünde alakasız bir metin döndü; görüntüleri özgün çözünürlükleriyle gönderin. Denememizde EV/dots-ocr örneği okudu, EV/deepseek-ocr-2 ise aynı görüntü için boş metin döndürdü; işe EV/dots-ocr ile başlayın.

B7. Konuşmadan metne

Bu, OpenAI ses API’sidir: file ve model alanlarıyla çok parçalı bir yükleme. Yanıt varsayılan olarak JSON’dur; response_format için text, srt ve vtt de çalışır. Evren zaman damgası döndürmediği için srt ve vtt tüm kaydı tek bir satırda taşır, verbose_json ise reddedilir.

curl -s $GW/v1/audio/transcriptions -H "Authorization: Bearer $BOSPHORUS_KEY" \
  -F model=EV/qwen3-asr-1.7b -F file=@note.wav | jq -r .text

Seslendirilmiş bir deneme cümlesi The meeting starts at 9:30 tomorrow morning. olarak geri geldi. Mac’te say -o note.aiff "…" ve ardından afconvert -f WAVE -d LEI16@16000 -c 1 note.aiff note.wav böyle bir kayıt üretir.

Bölüm C: her türü tek seferde deneyin

Bu betik kurulumunuzu kontrol eder ve her türü bir kez çağırır. Her kontrol için bir satır yazar ve bir şey başarısız olursa sıfırdan farklı bir kodla çıkar; böylece bir hatta duman testi olarak da çalışır. OCR’ı da denemek için OCR_IMAGE değişkenine üzerinde metin olan bir görüntü, konuşmadan metni denemek için de AUDIO_FILE değişkenine bir WAV dosyası verin.

#!/usr/bin/env python3
import math, os, sys, base64, mimetypes, requests

GW = os.environ.get("GW", "https://ai.corp.example").rstrip("/")
KEY = os.environ.get("BOSPHORUS_KEY") or sys.exit("set BOSPHORUS_KEY to your personal key")
H = {"Authorization": f"Bearer {KEY}"}
failed = 0


def post(path, body):
    r = requests.post(GW + path, headers=H, json=body, timeout=120)
    if r.status_code != 200:
        raise RuntimeError(f"HTTP {r.status_code}: {r.text[:300]}")
    return r.json()


def check(name, fn):
    global failed
    try:
        print(f"  ok    {name}: {fn()}")
    except Exception as e:
        failed += 1
        print(f"  FAIL  {name}: {e}")


def whoami():
    me = requests.get(GW + "/api/identity/me", headers=H, timeout=30).json()
    email = (me.get("user") or {}).get("email")
    assert email, "this key names no person: mint a personal key with ?client=api"
    return email


def evren_key():
    st = requests.get(GW + "/api/identity/evren-key", headers=H, timeout=30).json()
    status = (st.get("llm") or {}).get("status")
    assert status == "active", f"Evren LLM key status is {status!r}: save it on My variables"
    return status


def listing():
    data = requests.get(GW + "/v1/models", headers=H, timeout=30).json()["data"]
    ev = {m["id"]: m.get("type") for m in data if m["id"].startswith("EV/")}
    want = {"EV/qwen3-embedding-8b": "embedding", "EV/qwen3-reranker-8b": "rerank",
            "EV/clef": "decision", "EV/dots-ocr": "ocr", "EV/qwen3-guard-4b": "guard"}
    for mid, t in want.items():
        assert ev.get(mid) == t, f"{mid} is listed as {ev.get(mid)!r}, expected {t!r}"
    return f"{len(ev)} EV/ models, types as expected"


def chat():
    j = post("/v1/chat/completions", {"model": "EV/deepseek-v4-flash",
             "messages": [{"role": "user", "content": "Reply with the single word: pong"}]})
    text = j["choices"][0]["message"]["content"] or ""
    assert "pong" in text.lower(), repr(text)
    return text.strip()


def guard():
    j = post("/v1/chat/completions", {"model": "EV/qwen3-guard-4b",
             "messages": [{"role": "user", "content": "What is the weather in Izmir?"}]})
    text = j["choices"][0]["message"]["content"]
    assert text.startswith("Safety: Safe"), repr(text)
    return text.replace("\n", " / ")


def embeddings():
    j = post("/v1/embeddings", {"model": "EV/qwen3-embedding-8b", "input": [
        "How do I reset my VPN password?",
        "Steps to change the password of your VPN account",
        "The canteen serves lentil soup on Fridays"]})
    v = [d["embedding"] for d in j["data"]]
    cos = lambda a, b: sum(x * y for x, y in zip(a, b)) / (
        math.sqrt(sum(x * x for x in a)) * math.sqrt(sum(y * y for y in b)))
    related, unrelated = cos(v[0], v[1]), cos(v[0], v[2])
    assert len(v[0]) == 4096 and related > unrelated, (len(v[0]), related, unrelated)
    return f"{len(v[0])} dims, related {related:.3f} vs unrelated {unrelated:.3f}"


def rerank():
    docs = ["Bananas are yellow.", "Paris is the capital of France.", "Berlin is in Germany."]
    j = post("/v1/rerank", {"model": "EV/qwen3-reranker-8b",
             "query": "What is the capital of France?", "documents": docs})
    top = j["results"][0]
    assert top["index"] == 1, j["results"]
    return f"top: {docs[top['index']]!r} ({top['relevance_score']:.3f})"


def decision():
    j = post("/api/alpha/decisions", {"model": "EV/clef",
             "state": "Hi, I want my money back for the broken kettle.",
             "questions": {"intent": {"type": "choice", "instructions": "What does the customer want?",
                                      "criteria": {"refund": "money back",
                                                   "shipping": "where is my package",
                                                   "other": "anything else"}}}})
    a = j["answers"]["intent"]
    assert a["choice"] == "refund", a
    return f"choice {a['choice']} ({a['confidence']:.2f})"


def ocr():
    path = os.environ["OCR_IMAGE"]
    mime = mimetypes.guess_type(path)[0] or "image/png"
    data = base64.b64encode(open(path, "rb").read()).decode()
    text = post("/v1/ocr", {"model": "EV/dots-ocr", "image": f"data:{mime};base64,{data}"})["text"]
    assert text.strip(), "no text came back"
    return text.replace("\n", " / ")[:120]


def speech():
    with open(os.environ["AUDIO_FILE"], "rb") as f:
        r = requests.post(GW + "/v1/audio/transcriptions", headers=H, timeout=120,
                          data={"model": "EV/qwen3-asr-1.7b"}, files={"file": f})
    assert r.status_code == 200, f"HTTP {r.status_code}: {r.text[:300]}"
    return r.json()["text"]


def wrong_endpoint():
    r = requests.post(GW + "/v1/chat/completions", headers=H, timeout=60,
                      json={"model": "EV/qwen3-reranker-8b",
                            "messages": [{"role": "user", "content": "hi"}]})
    assert r.status_code == 400 and "/v1/rerank" in r.text, f"HTTP {r.status_code}: {r.text[:200]}"
    return "400, names /v1/rerank"


print(f"gateway {GW}")
for name, fn in [("personal key", whoami), ("Evren key", evren_key), ("model listing", listing),
                 ("chat", chat), ("guard", guard), ("embeddings", embeddings),
                 ("rerank", rerank), ("decision", decision),
                 ("wrong endpoint is refused", wrong_endpoint)]:
    check(name, fn)
if os.environ.get("OCR_IMAGE"):
    check("ocr", ocr)
if os.environ.get("AUDIO_FILE"):
    check("speech to text", speech)
print("all passed" if not failed else f"{failed} failed")
sys.exit(1 if failed else 0)

evren_smoke.py adıyla kaydedin, requests kütüphanesini kurun ve python3 evren_smoke.py ile çalıştırın. Başarılı bir çalışma all passed ile biter.

Bir şey ters gittiğinde

Gördüğünüz Ne yapmalı
503 “EV/…” is served with YOUR OWN Evren key and you have not registered one Evren LLM anahtarınızı My variables sayfasına kaydedin (A1).
503 … this request carries no user identity to look one up for Bir ekip ya da servis anahtarı gönderdiniz. Kişisel anahtarınızı kullanın (A2).
400 “qwen3-reranker-8b” is a rerank model — use POST /v1/rerank, not /v1/chat/completions Mesajın adını verdiği uç noktayı çağırın.
404 … does not serve /v1/rerank — it is served by Evren rerank models only O türde bir EV/ modeli kullanın.
400 field “image” is required … OCR için "image": "data:image/png;base64,…" gönderin.
400 a choice question takes ‘criteria’ … Liste ya da nesne olarak criteria kullanın.
400 Currently do not support verbose_json … Konuşmadan metne için json, text, srt ya da vtt kullanın.
finish_reason: "length" ile boş bir sohbet yanıtı Düşünen bir model max_tokens değerini düşünmeye harcadı. Değeri artırın ya da hiç vermeyin.
401 invalid api key Anahtar iptal edilmiş ya da yanlış yazılmış, ya da Evren anahtarınızın kendisini gönderdiniz. gpk_… anahtarınızı gönderin ya da &rotate=true ile yenisini üretin (A3).
429 Bir hız limiti. retry-after başlığındaki süre kadar bekleyin.

Her çağrı, uç noktasıyla birlikte etkinlik sayfasında sizin adınızla görünür.