العودة إلى المدونة

API وSDKدليل

أول طلب في Go مع openai-go: عنوان URL الأساسي، المفتاح، usage

برنامج Go كامل يستدعي نموذج CheapTokens عبر openai-go ويطبع الإجابة وfinish_reason واستخدام الرموز، مع إعادات المحاولة ومهلة.

بواسطة CheapTokens Teamنُشر في 5 دقيقة قراءة

الغلاف: أول طلب في Go مع حزمة openai-go SDK، طرفية بها go run والإجابة وfinish_reason وusage
في هذه الصفحة
  1. ما تحتاجه قبل أن تبدأ
  2. البرنامج كاملًا
  3. اقرأ الإجابة وfinish_reason وusage
  4. إعادة المحاولة والمهلات: ثلاثة حدود مختلفة
  5. تكلفة ألف من هذه الاستدعاءات
  6. إذا لم يعمل

لديك بالفعل شيفرة Go تتحدث إلى واجهة برمجة تطبيقات بنمط OpenAI، أو أنك على وشك كتابة بعض منها. لإرسالها إلى CheapTokens تغيّر خيارين على العميل وسلسلة واحدة، وهي معرّف النموذج. تبقى حزمة SDK كما هي: حزمة openai-go الرسمية، الإصدار v3.

فيما يلي البرنامج كاملًا، ثم ما يفعله كل سطر، وكيف تقرأ الإجابة وعدد الرموز، وكيف تمنع طلبًا عالقًا من تعليق خدمتك. تم التحقق من الإصدارات مقابل ملف README الخاص بـ openai-go في 3 نوفمبر 2026: أحدث وسم في تلك الصفحة هو v3.91.1، وهو يتطلب Go 1.26 أو أحدث.

ما تحتاجه قبل أن تبدأ#

  • Go 1.26 أو أحدث. على Go 1.25 ثبّت v3.74.0؛ وعلى Go 1.22–1.24 ثبّت v3.44.0 (يقول ملف README إن السلسلة الأقدم لا تحصل على إصلاحات مضمونة).
  • مفتاح API من CheapTokens. احتفظ به في متغير بيئة، لا في ملف المصدر.
  • عنوان API: https://api.cheaptokens.dev/v1. يتحدث تنسيق OpenAI Chat Completions، لذا يعمل openai-go دون غلاف. تحتوي الوثائق على العنوان نفسه وصفحة المفتاح.
  • معرّف نموذج. نستخدم deepseek-ai/DeepSeek-V4-Flash-0731: سياق 380K وحتى 32,768 رمزًا في إجابة واحدة. استخدم المعرّف الكامل؛ فالاسم المختصر من جداول الأسعار لا تقبله API.

خطوة بخطوة

إعداد المشروع

تثبيت SDK

في مجلد فارغ:

bash
go mod init example.com/first-request
go get -u 'github.com/openai/openai-go/[email protected]'

مسار الاستيراد هو github.com/openai/openai-go/v3، واسم الحزمة هو openai.

ضع المفتاح في البيئة

bash
export CHEAPTOKENS_API_KEY="paste-your-key-here"

على Windows PowerShell: $env:CHEAPTOKENS_API_KEY = "paste-your-key-here". العنصر النائب ليس مفتاحًا حقيقيًا.

أنشئ main.go وشغّله

الصق البرنامج من القسم التالي في main.go، ثم شغّل go run ..

البرنامج كاملًا#

go
package main

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

	"github.com/openai/openai-go/v3"
	"github.com/openai/openai-go/v3/option"
)

func main() {
	client := openai.NewClient(
		option.WithBaseURL("https://api.cheaptokens.dev/v1"),
		option.WithAPIKey(os.Getenv("CHEAPTOKENS_API_KEY")),
		option.WithMaxRetries(2),
		option.WithRequestTimeout(30*time.Second),
	)

	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
	defer cancel()

	resp, err := client.Chat.Completions.New(ctx, openai.ChatCompletionNewParams{
		Model: "deepseek-ai/DeepSeek-V4-Flash-0731",
		Messages: []openai.ChatCompletionMessageParamUnion{
			openai.UserMessage("Explain in two sentences what a token is."),
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	if len(resp.Choices) == 0 {
		log.Fatal("no choices in the response")
	}

	fmt.Println(resp.Choices[0].Message.Content)
	fmt.Println("finish_reason:", resp.Choices[0].FinishReason)
	fmt.Println("input tokens:", resp.Usage.PromptTokens)
	fmt.Println("output tokens:", resp.Usage.CompletionTokens)
	fmt.Println("total tokens:", resp.Usage.TotalTokens)
}
مسار طلب واحد: المفتاح من البيئة، عميل openai-go، إكمال الدردشة، ثم content وfinish_reason وusage
ما يفعله البرنامج، بالترتيب

الأجزاء المهمة:

  • option.WithBaseURL(...) هو السطر الوحيد الذي ينقل SDK من OpenAI إلى CheapTokens. استخدم العنوان تمامًا كما في الوثائق.
  • option.WithAPIKey(os.Getenv(...)) يمرر المفتاح صراحةً. بدونه يقرأ العميل OPENAI_API_KEY، وهو مفيد عند نقل شيفرة موجودة: اضبط ذلك المتغير على مفتاح CheapTokens ولن تحتاج الشيفرة إلى تغيير المفتاح. الأمر نفسه ينطبق على OPENAI_BASE_URL، لكن WithBaseURL الصريح يتجاوزه، فلا مفاجآت إن وُجد الاثنان.
  • Model سلسلة عادية في SDK (ChatModel اسم بديل لـ string)، لذا يعمل أي معرّف نموذج، وليس فقط الثوابت التي يعرضها ملف README.
  • openai.UserMessage(...) دور مستخدم واحد. يستخدم مثال README DeveloperMessage وثابت GPT؛ هنا تكفي رسالة مستخدم ومعرّف نصي.

اقرأ الإجابة وfinish_reason وusage#

الثلاثة جميعًا تأتي من حقول يحللها SDK لك بالفعل:

  • resp.Choices[0].Message.Content هو النص (string).
  • resp.Choices[0].FinishReason أيضًا string. stop يعني أن النموذج انتهى من تلقاء نفسه؛ length يعني أن الإجابة بلغت حد الرموز وقُطعت. إذا رأيت length، فاقرأ لماذا تتوقف الإجابة في منتصف الجملة.
  • resp.Usage يحمل PromptTokens (ما أرسلته)، وCompletionTokens (ما كتبه النموذج) وTotalTokens، وكلها int64.

سيبدو المخرجات هكذا: الإجابة، ثم finish_reason: بقيمة، ثم ثلاثة أعداد للرموز. تختلف الأرقام في كل تشغيل، لذا سجّلها. فهي ما تدفع مقابله، ورموز المخرجات هي الجانب الأغلى.

جرّب بنفسكجرّب: ما الذي يتغير إذا بدّلت النموذج؟إظهار الإجابة

غيّر سلسلة Model إلى zai-org/GLM-5.3-Flash وشغّل مرة أخرى. لا يتحرك أي شيء آخر في البرنامج. سيختلف نص الإجابة وأرقام usage الثلاثة، وهي أسرع طريقة لمقارنة نموذجين على موجّهك الخاص. يمتلك GLM-5.3-Flash سياقًا 390K وحتى 8,192 رمزًا في إجابة واحدة.

إعادة المحاولة والمهلات: ثلاثة حدود مختلفة#

هنا تتضرر خدمات Go عادةً: افتراضيًا لا يملك SDK أي مهلة على الإطلاق، لذا يمكن لاتصال متعطل أن ينتظر إلى الأبد. ثلاثة إعدادات تصلح ذلك، وهي تعمل على مستويات مختلفة:

  • option.WithMaxRetries(2): يعيد SDK محاولة أخطاء الاتصال و408 و409 و429 و5xx بانتظار أسي قصير. إعادتان هما الافتراضي بالفعل؛ 0 يوقف إعادة المحاولة. يمكنك ضبطه على العميل، أو على استدعاء واحد.
  • option.WithRequestTimeout(30*time.Second): الحد لمحاولة واحدة.
  • مهلة context: الحد للاستدعاء بأكمله، بما في ذلك إعادات المحاولة والانتظار.

لذا مع إعادتين يمكن أن تكون هناك حتى 3 محاولات: 3 × 30 = 90 ثانية انتظار في أسوأ الحالات، إضافةً إلى التوقفات القصيرة بين المحاولات. سياق من دقيقتين يغطي ذلك. إذا أردت قاعدة صارمة بإجابة خلال 20 ثانية لمعالج ويب، فقصّر السياق، لا مهلة المحاولة الواحدة فقط.

الافتراضيات مقارنةً بالإعدادات في البرنامج: إعادتان في كليهما، لا مهلة افتراضيًا مقابل مهلة محاولة 30 ثانية
الافتراضيات مقابل البرنامج أعلاه

لمزيد من الخلفية حول اختيار هذه الأرقام، توجد نسخة Python من النصيحة نفسها في مهلة وإعادات محاولة OpenAI Python SDK. المنطق ينتقل إلى Go.

تكلفة ألف من هذه الاستدعاءات#

لنفترض أنك تشغّل خدمة صغيرة تجري 1,000 طلب يوميًا، كل منها بنحو 800 رمز إدخال و300 رمز إخراج. على deepseek-ai/DeepSeek-V4-Flash-0731 يكلف ذلك اليوم $0.042 (1,000 × 800 رمز إدخال، 1,000 × 300 رمز إخراج). يعرض الجدول الحمل نفسه عبر نماذجنا؛ محسوبًا بالإجمالي، مع الإدخال والإخراج معًا، فهو أرخص من OpenRouter.

النموذج لكل طلب 1,000 طلبات OpenRouter، 1,000 طلبات
GLM-5.3-Flash $0.000028 $0.028 $0.0517
DeepSeek-V4-Flash $0.000042 $0.042 $0.098
MiniMax-M2.7 $0.000085 $0.085 $1.02

800 رمز إدخال و300 رمز إخراج لكل طلب. الأسعار لكل مليون رمز حالية وتتغير مع تعريفاتنا؛ يعرض عمود OpenRouter أسعارًا مرجعية لنفس حجم العمل.

أدخل أرقامك الخاصة. يطبع تشغيلك الأول PromptTokens وCompletionTokens الحقيقيين، فلا تحتاج إلى تخمين المتوسط:

حاسبة التكلفة

يوم واحد من خدمة Go صغيرة

رموز الإدخال لكل طلب: 800 · رموز الإخراج لكل طلب: 300 · الطلبات يوميًا: 1,000

النموذجيوميًاشهريًا
GLM-5.3-Flash$0.028$0.84
DeepSeek-V4-Flash$0.042$1.26
MiniMax-M2.7$0.085$2.55

الأسعار في صفحة التسعير وصفحة النماذج حية وتستخدم سعرًا ثابتًا واحدًا لكل نموذج، دون ساعات ذروة.

إذا لم يعمل#

  • يذكر الخطأ 401: المفتاح فارغ أو خاطئ. يعيد os.Getenv سلسلة فارغة لمتغير غير مضبوط، لذا تحقق من echo $CHEAPTOKENS_API_KEY في الطرفية نفسها التي تشغّل فيها go run ..
  • يذكر الخطأ 404 أو نموذجًا غير معروف: المعرّف. انسخه كاملًا، مع بادئة deepseek-ai/. يمكنك سرد المعرّفات في استدعاء قائمة النماذج.
  • go: module requires Go 1.26: سلسلة أدواتك أقدم. ثبّت وسم SDK أقدم كما هو موضح في الأعلى.
  • يتعلق الاستدعاء ثم يفشل: هذه هي المهلة تؤدي عملها. تحقق من مسار الشبكة أولًا، ثم ارفع WithRequestTimeout إذا كان النموذج يحتاج فعلًا وقتًا أطول لإجابة طويلة.

إذا كانت فكرة عنوان URL الأساسي جديدة عليك، فـما هو base_url وكيف تبدّل يشرحها دون شيفرة.