OpenAI SDK ile Ollama API Fonksiyon Çağırma Örneği
Fonksiyon çağırma, modelin kodunuzun bir fonksiyonu çalıştırmasını ve sonucu yanıtında kullanmasını sağlar. Aşağıda, barındırılan bir uç noktaya yönelik OpenAI SDK ile tam bir örnek, akış ve çoğu hataya neden olan hatalar yer almaktadır.
Güncellendi

Temel noktalar
- Fonksiyonunuzu ⟦tools⟧ içinde bir JSON şeması olarak gönderin; model, metin yerine ⟦tool_calls⟧ ile yanıt verir.
- Fonksiyonu çalıştırın, sonucu role tool mesajı olarak ekleyin ve API'ye tekrar istek gönderin.
- Model hatalı veya beklenmedik JSON döndürebileceğinden, argümanları her zaman savunmacı şekilde ayrıştırın.
- Akışlı araç çağrıları, indekslerine göre birleştirmeniz gereken parçalar halinde gelir.
Döngünün görünümü
Barındırılan bir uç noktaya karşı çalışan bir ollama API fonksiyon çağırma örneği arıyorsanız, yapı standart OpenAI şemasıdır. İşlevlerinizi bir tools dizisi içinde tanımlarsınız. Model ya metinle yanıt verir ya da işlevin adını ve argümanlarını içeren bir tool_calls listesi döndürür. Model hiçbir şey çalıştırmaz. İşlevi sizin kodunuz çalıştırır, çıktıyı geri gönderir ve model nihai yanıtı yazar.
Bu, bir araç kullanımının bir gidiş-dönüşü için iki API çağrısı yapar:
- Kullanıcı mesajını ve araç tanımlarını gönderin.
tool_callsiçeren bir asistan mesajı alın. Her çağrıyı yerelde çalıştırın.- Orijinal mesajları, asistan mesajını ve her çağrı için bir
role: "tool"mesajını sonucu ile birlikte gönderin. - Nihai metin yanıtını alın.
Örnekler base URL olarak https://api.ollamaapi.com/v1 ve model ID olarak uncensored kullanır. Uç nokta barındırılan bir hizmet olduğundan, anahtar API anahtarı sayfasından gelir. Yerel bir Ollama sunucusuna karşı da çalışır, base URL'i, anahtarı ve model adını değiştirirseniz, yerel model araçları desteklediği sürece.
Tam bir Python örneği
Örnek, küçük bir sözlük tarafından desteklenen get_order_status adlı bir işlev verir. Gerçek bir uygulama, bu noktada bir veritabanına veya dahili bir servise sorgu yapar.
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.ollamaapi.com/v1", api_key="YOUR_KEY")
ORDERS = {"A1001": "shipped", "A1002": "processing", "A1003": "delivered"}
def get_order_status(order_id: str) -> str:
return ORDERS.get(order_id, "not found")
tools = [{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Look up the status of an order by its ID.",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "Order ID such as A1001"}
},
"required": ["order_id"],
},
},
}]
messages = [{"role": "user", "content": "Where is order A1002?"}]
first = client.chat.completions.create(
model="uncensored",
messages=messages,
tools=tools,
tool_choice="auto",
)
msg = first.choices[0].message
if msg.tool_calls:
messages.append(msg) # keep the assistant turn with its tool_calls
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = get_order_status(**args)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": result,
})
final = client.chat.completions.create(
model="uncensored",
messages=messages,
tools=tools,
)
print(final.choices[0].message.content)
else:
print(msg.content)Burada üç ayrıntı önemlidir. tool_calls içeren asistan mesajı, araç sonuçlarından önce geçmişe geri eklenmelidir, aksi takdirde sonraki istek reddedilir veya karıştırılır. Her araç mesajı, yanıt verdiği çağrının tool_call_id değerini taşımalıdır. Ve ikinci istek hala tools içermelidir, çünkü model ilk sonucu gördükten sonra başka bir fonksiyon çağırmak isteyebilir.
curl ile aynı istek
curl ile test etmek SDK'yı resmin dışında bırakır; bu da sorunun kodunuzda mı yoksa istekte mi olduğunu emin olamadığınızda yardımcı olur.
curl https://api.ollamaapi.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "uncensored",
"messages": [{"role": "user", "content": "Where is order A1002?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Look up the status of an order by its ID.",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"]
}
}
}],
"tool_choice": "auto"
}'Başarılı bir ilk yanıtta finish_reason, tool_calls olarak ayarlanmıştır, content boş veya null'dur ve bir tool_calls dizisi vardır. arguments alanı JSON içeren bir dizgedir, iç içe bir nesne değildir; bu nedenle Python örneği json.loads çağrısını yapar.
tool_choice alanı isteğin ne kadar baskın olduğunu kontrol eder. auto modelin karar vermesine olanak tanır. Bir işlevin adını içeren bir nesne geçmek, o belirli işlevi ister. Bir nedeniniz yoksa auto kullanın; çünkü bir çağrıyı, gerektirmeyen bir mesajda zorlamak uydurma argümanlar üretir.
Node ile aynı döngü
Node sürümü resmi openai paketini kullanır ve aynı adımları izler. Bu sürüm, Promise.all ile her dönüşte birden fazla çağrıyı işler.
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.ollamaapi.com/v1",
apiKey: process.env.API_KEY,
});
const handlers = {
get_order_status: async ({ order_id }) =>
({ A1001: "shipped", A1002: "processing" })[order_id] ?? "not found",
};
const tools = [{
type: "function",
function: {
name: "get_order_status",
description: "Look up the status of an order by its ID.",
parameters: {
type: "object",
properties: { order_id: { type: "string" } },
required: ["order_id"],
},
},
}];
const messages = [{ role: "user", content: "Where is order A1001?" }];
const first = await client.chat.completions.create({
model: "uncensored", messages, tools,
});
const msg = first.choices[0].message;
if (msg.tool_calls?.length) {
messages.push(msg);
const results = await Promise.all(msg.tool_calls.map(async (call) => {
const args = JSON.parse(call.function.arguments);
const out = await handlers[call.function.name](args);
return { role: "tool", tool_call_id: call.id, content: String(out) };
}));
messages.push(...results);
const final = await client.chat.completions.create({
model: "uncensored", messages, tools,
});
console.log(final.choices[0].message.content);
} else {
console.log(msg.content);
}Akışlı fonksiyon çağrıları
stream: true ile yanıt SSE üzerinden gelir ve araç çağrıları parçalar halinde gelir. Her parça, bir index ile bir delta.tool_calls girişi taşır. Bir indeks için ilk parça, çağrı kimliğini ve fonksiyon adını içerir. Sonraki parçalar arguments dizisinin dilimlerini ekler. Dilimleri indeks başına birleştirin ve akış bittikten sonra JSON'u ayrıştırın.
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Where is order A1003?"}],
tools=tools,
stream=True,
)
calls = {}
for chunk in stream:
if not chunk.choices:
continue
delta = chunk.choices[0].delta
for part in (delta.tool_calls or []):
slot = calls.setdefault(part.index, {"id": "", "name": "", "args": ""})
if part.id:
slot["id"] = part.id
if part.function and part.function.name:
slot["name"] = part.function.name
if part.function and part.function.arguments:
slot["args"] += part.function.arguments
for slot in calls.values():
print(slot["name"], json.loads(slot["args"]))Akışlı bir isteğin, akış bitene kadar eşzamanlılık slotunu koruduğunu unutmayın. Tam anahtar aynı anda 8 isteğe ve dakikada 300 isteğe izin verir; deneme anahtarı 2 ve 60'a izin verir. Çok sayıda kullanıcı için paralel olarak araç döngüleri çalıştırıyorsanız, her açık akışı ilk sayıya (limit) dahil edin.
Tuzaklar ve nasıl düzeltilecekleri
Hatalı veya eksik argümanlar
Model bir açık ağırlıklı modeldir ve açık modeller bazı geçerli olmayan JSON argümanları döndürebilir, gerekli bir alanı bırakabilir veya ekstra bir alan uydurabilir. json.loads'i bir try bloğu içine alın, şemanıza göre doğrulayın ve başarısız olduğunda hatayı bir tool mesajı olarak gönderin. Model genellikle bir sonraki adımda kendini düzeltir. Sabit bir hatanın sonsuza kadar devam etmesini önlemek için döngüyü birkaç yinelemede sınırlayın.
Çok belirsiz açıklamalar
Model, işlevin adını ve açıklamasını okuyarak bir işlev seçer. "Veri alır" gibi bir açıklama, modelin çalışacağı bir şey vermez. İşlevin ne yaptığını, girdilerin ne anlama geldiğini ve parametre açıklamasında bir örnek değer dahil edin.
Aynı anda çok fazla araç
Her araç tanımı, her istekte giriş token'ı olarak sayılır. 1 milyon token başına $0.15 fiyatla, 150 token'lık on araç 1.500 token ekler; bu da istek başına $0,000225 eder, küçük ama hacimle sıfır değildir. Daha önemlisi, uzun bir menü seçimi daha az güvenilir kılar. Sadece mevcut adım için ilgili araçları sunun.
Çok büyük araç sonuçları
Ne döndürürseniz, girdi olarak geri beslenir. Büyük veritabanı satırlarını veya web sayfalarını modelin ihtiyaç duyduğu alanlarla sınırlayın. Bağlam penceresi toplamda 100.000 token'dır, bu nedenle çok büyük bir sonuç konuşmayı dışlayabilir.
Araçları JSON moduyla karıştırmak
JSON modu (response_format ile json_object) mevcuttur, ancak bunu nihai cevap için kullanın, modelin fonksiyon çağırmasını istediğiniz dönüşler için değil. Buna güvenmeden önce kendi istemlerinizde kombinasyonu test edin.
Yerel Ollama'dan geçiş ve kontrol edilecekler
İlk araç döngünüzü yerel bir Ollama sunucusuna karşı oluşturduysanız, neredeyse hiçbir şey değişmez. Base URL'yi https://api.ollamaapi.com/v1 ile değiştirin, gerçek bir anahtar kullanın ve modeli uncensored olarak ayarlayın. /api/chat gibi yerel Ollama rotaları burada mevcut değil. Sadece POST /v1/chat/completions ve GET /v1/models mevcuttur, bu nedenle yerel API için yazılan kod, OpenAI tarzı çağrıyı kullanmalıdır.
Göndermeden önce bu kısa kontrol listesini çalıştırın:
- Anahtarın
GET /v1/modelsile çalıştığını onaylayın. - Her çağrı için
X-Request-Idbaşlığını günlüğe kaydedin, böylece başarısız bir çalıştırma izlenebilir. - Araç döngülerini denetimsiz çalıştırıyorsanız, yanıt başlıklarında
X-Balance-USD'i izleyin. - HTTP 429'ı işleyin:
rate_limitedveyaconcurrencydurumlarında bekleyin ve aşırı yüklenme durumundaRetry-After: 5başlığını uygulayın. - Yineleme sayıları için bir üst sınır belirleyin.
Bir araç döngüsü, kullanıcı sorusu başına en az iki istek yapar, bu nedenle maliyetler bununla ölçeklenir. Örneğin, isteği başına 1.200 giriş token'ı ve 150 çıkış token'ı ile 2.000 döngü, her biri iki istek olmak üzere, 4.000 istek, 4,8M giriş token'ı ve 0,6M çıkış token'ı eder. Bu, $0.72 artı $0,30 veya toplamda $1,02 eder. Fiyatlandırma sayfası bakiye yükleme seçeneklerini içerir ve dokümantasyon desteklenen istek alanlarını listeler. Yeni kullanıcılar, kart gerektirmeyen $0,50 deneme kredisi ile bunların tümünü deneyebilir.
Daha fazla kılavuz
Sorular ve cevaplar
Uç nokta fonksiyon çağırma desteği sağlıyor mu?
Evet. Araçları ve tool_choice'u kabul eder, tool_calls döndürür, bunları delta olarak akışa alır ve sonuçları role: tool mesajı olarak geri alır.
İkinci istek neden bir araç çağrısından sonra başarısız oluyor?
Yaygın neden, eksik bir asistan mesajı veya eşleşmeyen tool_call_id'si olan bir araç mesajıdır. Araç çağrıları içeren asistan dönüşünü önce ekleyin, ardından her çağrı için bir araç mesajı ekleyin.
Model bir dönüşte birkaç aracı çağırabilir mi?
Birden fazla öğe içeren bir liste döndürebilir, bu nedenle tüm bunlar üzerinde döngü kurun ve her biri için bir sonuç gönderin. Listenin tek bir öğe içerdiğini varsaymayın.
Bunun için Ollama kütüphanesine ihtiyacım var mı?
Hayır. Resmi OpenAI SDK'ları yeterlidir. Base URL'yi uç noktaya işaret edin ve uncensored modelini kullanın.
Anahtarınız tek bir formun uzağında
Bir hesap oluşturun, anahtarı kopyalayın ve base URL'yi değiştirin. Kurulum bu kadar.