نعلن اليوم عن Swift-huggingface، وهي حزمة Swift جديدة توفر عميلاً كاملاً لـ Hugging Face Hub.
يمكنك البدء في استخدامه اليوم كحزمة مستقلة، وسيتم دمجه قريبًا في محولات Swift كبديل لحزمة الحالية HubApi تطبيق.
المشكلة
عندما أطلقنا برنامج Swift-Transformers 1.0 في وقت سابق من هذا العام، سمعنا صوتًا عاليًا وواضحًا من المجتمع:
- كانت التنزيلات بطيئة وغير موثوقة.
قد تفشل ملفات النماذج الكبيرة (غالبًا عدة غيغابايت) جزئيًا دون أي وسيلة للاستئناف. لجأ المطورون إلى تنزيل النماذج يدويًا وتجميعها مع تطبيقاتهم، مما أدى إلى هزيمة غرض التحميل الديناميكي للنماذج. - لا توجد ذاكرة تخزين مؤقت مشتركة مع نظام بايثون البيئي.
بايثونtransformersنماذج مخازن المكتبة في~/.cache/huggingface/hub. تم تنزيل تطبيقات Swift إلى موقع مختلف وببنية مختلفة. إذا كنت قد قمت بالفعل بتنزيل نموذج باستخدام Python CLI، فيمكنك تنزيله مرة أخرى لتطبيق Swift الخاص بك. - المصادقة مربكة.
من أين يجب أن تأتي الرموز؟ متغيرات البيئة؟ الملفات؟ سلسلة المفاتيح؟ الجواب هو “هذا يعتمد”، ولم يجعل التنفيذ الحالي الخيارات واضحة.
تقديم الوجه السريع المعانقة
Swift-huggingface عبارة عن إعادة كتابة شاملة تركز على الموثوقية وتجربة المطورين. وهو يوفر:
- تغطية كاملة لواجهة برمجة تطبيقات Hub — النماذج، ومجموعات البيانات، والمساحات، والمجموعات، والمناقشات، والمزيد
- عمليات ملف قوية – تتبع التقدم ودعم السيرة الذاتية والتعامل مع الأخطاء بشكل صحيح
- ذاكرة التخزين المؤقت المتوافقة مع بايثون – مشاركة النماذج التي تم تنزيلها بين عملاء Swift وPython
- مصادقة مرنة – أ
TokenProviderالنمط الذي يجعل مصادر الاعتماد واضحة - دعم OAuth – دعم من الدرجة الأولى للتطبيقات التي تواجه المستخدم والتي تحتاج إلى مصادقة المستخدمين
- دعم الواجهة الخلفية للتخزين Xet (قريباً!) – إلغاء البيانات المكررة على أساس القطعة لإجراء تنزيلات أسرع بشكل ملحوظ
دعونا نلقي نظرة على بعض الأمثلة.
مصادقة مرنة مع TokenProvider
أحد أكبر التحسينات هو كيفية عمل المصادقة. ال TokenProvider يوضح النمط من أين تأتي بيانات الاعتماد:
import HuggingFace
let client = HubClient.default
let client = HubClient(tokenProvider: .static("hf_xxx"))
let client = HubClient(tokenProvider: .keychain(service: "com.myapp", account: "hf_token"))
يتبع الاكتشاف التلقائي نفس الاصطلاحات التي تتبعها لغة Python huggingface_hub مكتبة:
HF_TOKENمتغير البيئةHUGGING_FACE_HUB_TOKENمتغير البيئةHF_TOKEN_PATHمتغير البيئة (المسار إلى ملف الرمز المميز)$HF_HOME/tokenملف~/.cache/huggingface/token(موقع HF CLI القياسي)~/.huggingface/token(الموقع الاحتياطي)
هذا يعني إذا كنت قد قمت بتسجيل الدخول بالفعل باستخدام hf auth login، سوف يقوم Swift-huggingface تلقائيًا بالعثور على هذا الرمز واستخدامه.
OAuth للتطبيقات التي تواجه المستخدم
هل تريد إنشاء تطبيق حيث يقوم المستخدمون بتسجيل الدخول باستخدام حساب Hugging Face الخاص بهم؟ يتضمن Swift-huggingface تطبيقًا كاملاً لـ OAuth 2.0:
import HuggingFace
let authManager = try HuggingFaceAuthenticationManager(
clientID: "your_client_id",
redirectURL: URL(string: "yourapp://oauth/callback")!,
scope: [.openid, .profile, .email],
keychainService: "com.yourapp.huggingface",
keychainAccount: "user_token"
)
try await authManager.signIn()
let client = HubClient(tokenProvider: .oauth(manager: authManager))
let userInfo = try await client.whoami()
print("Signed in as: \(userInfo.name)")
يتعامل مدير OAuth مع تخزين الرمز المميز في Keychain، والتحديث التلقائي، وتسجيل الخروج الآمن. لا مزيد من إدارة الرمز المميز يدويًا.
تنزيلات موثوقة
أصبح الآن تنزيل النماذج الكبيرة أمرًا سهلاً بفضل تتبع التقدم المناسب ودعم الاستئناف:
let progress = Progress(totalUnitCount: 0)
Task {
for await _ in progress.publisher(for: \.fractionCompleted).values {
print("Download: \(Int(progress.fractionCompleted * 100))%")
}
}
let fileURL = try await client.downloadFile(
at: "model.safetensors",
from: "microsoft/phi-2",
to: destinationURL,
progress: progress
)
إذا تمت مقاطعة التنزيل، يمكنك استئنافه:
let fileURL = try await client.resumeDownloadFile(
resumeData: savedResumeData,
to: destinationURL,
progress: progress
)
لتنزيل مستودعات النماذج بأكملها،
downloadSnapshot يعالج كل شيء:
let modelDir = try await client.downloadSnapshot(
of: "mlx-community/Llama-3.2-1B-Instruct-4bit",
to: cacheDirectory,
matching: ["*.safetensors", "*.json"],
progressHandler: { progress in
print("Downloaded \(progress.completedUnitCount) of \(progress.totalUnitCount) files")
}
)
تقوم وظيفة اللقطة بتتبع البيانات التعريفية لكل ملف، لذا فإن الاستدعاءات اللاحقة تقوم فقط بتنزيل الملفات التي تم تغييرها.
ذاكرة التخزين المؤقت المشتركة مع بايثون
تذكر المشكلة الثانية التي ذكرناها؟
“لا توجد ذاكرة تخزين مؤقت مشتركة مع نظام بايثون البيئي.”
لقد تم حل هذا الآن.
يطبق Swift-huggingface بنية ذاكرة التخزين المؤقت المتوافقة مع Python والتي تسمح بالمشاركة السلسة بين عملاء Swift وPython:
~/.cache/huggingface/hub/
├── models--deepseek-ai--DeepSeek-V3.2/
│ ├── blobs/
│ │ └── <etag> # actual file content
│ ├── refs/
│ │ └── main # contains commit hash
│ └── snapshots/
│ └── <commit_hash>/
│ └── config.json # symlink → ../../blobs/<etag>
هذا يعنى:
- قم بالتنزيل مرة واحدة، واستخدمه في كل مكان.
إذا كنت قد قمت بالفعل بتنزيل نموذج باستخدام ملفhfCLI أو مكتبة Python، سيجدها Swift-huggingface تلقائيًا. - التخزين الموجه للمحتوى.
يتم تخزين الملفات بواسطة ETag الخاصة بها في ملفblobs/دليل. إذا شاركت مراجعتان في نفس الملف، فسيتم تخزينهما مرة واحدة فقط. - روابط رمزية لتحقيق الكفاءة.
تحتوي أدلة اللقطات على روابط رمزية إلى النقط، مما يقلل من استخدام القرص مع الحفاظ على بنية ملف نظيفة.
يتبع موقع ذاكرة التخزين المؤقت نفس اصطلاحات متغيرات البيئة مثل Python:
HF_HUB_CACHEمتغير البيئةHF_HOMEمتغير البيئة +/hub~/.cache/huggingface/hub(تقصير)
يمكنك أيضًا استخدام ذاكرة التخزين المؤقت مباشرة:
let cache = HubCache.default
if let cachedPath = cache.cachedFilePath(
repo: "deepseek-ai/DeepSeek-V3.2",
kind: .model,
revision: "main",
filename: "config.json"
) {
let data = try Data(contentsOf: cachedPath)
}
لمنع حالات السباق عندما تصل عمليات متعددة إلى نفس ذاكرة التخزين المؤقت، يستخدم Swift-huggingface قفل الملفات (flock(2)).
قبل وبعد
إليك ما يبدو عليه تنزيل لقطة النموذج مع النسخة القديمة HubApi:
let hub = HubApi()
let repo = Hub.Repo(id: "mlx-community/Llama-3.2-1B-Instruct-4bit")
let modelDir = try await hub.snapshot(
from: repo,
matching: ["*.safetensors", "*.json"]
) { progress in
print(progress.fractionCompleted)
}
وإليكم نفس العملية مع العناق السريع للوجه:
let client = HubClient.default
let modelDir = try await client.downloadSnapshot(
of: "mlx-community/Llama-3.2-1B-Instruct-4bit",
to: cacheDirectory,
matching: ["*.safetensors", "*.json"],
progressHandler: { progress in
print("\(progress.completedUnitCount)/\(progress.totalUnitCount) files")
}
)
واجهة برمجة التطبيقات (API) متشابهة، لكن التنفيذ مختلف تمامًا – مبني عليها URLSession قم بتنزيل المهام من خلال التعامل المناسب مع المندوب ودعم بيانات السيرة الذاتية وتتبع البيانات التعريفية.
أبعد من التنزيلات
ولكن انتظر، هناك المزيد! يحتوي Swift-huggingface على عميل Hub كامل:
let models = try await client.listModels(
filter: "library:mlx",
sort: "trending",
limit: 10
)
let model = try await client.getModel("mlx-community/Llama-3.2-1B-Instruct-4bit")
print("Downloads: \(model.downloads ?? 0)")
print("Likes: \(model.likes ?? 0)")
let collections = try await client.listCollections(owner: "huggingface", sort: "trending")
let discussions = try await client.listDiscussions(kind: .model, "username/my-model")
وهذا ليس كل شيء! يحتوي Swift-huggingface على كل ما تحتاجه للتفاعل مع Hugging Face Inference Providers، مما يمنح تطبيقك إمكانية الوصول الفوري إلى مئات من نماذج التعلم الآلي، المدعومة بموفري استدلال عالميين:
import HuggingFace
let client = InferenceClient.default
let response = try await client.textToImage(
model: "black-forest-labs/FLUX.1-schnell",
prompt: "A serene Japanese garden with cherry blossoms",
provider: .hfInference,
width: 1024,
height: 1024,
numImages: 1,
guidanceScale: 7.5,
numInferenceSteps: 50,
seed: 42
)
try response.image.write(to: URL(fileURLWithPath: "generated.png"))
تحقق من الملف التمهيدي للحصول على قائمة كاملة بكل ما هو مدعوم.
ما هو التالي
نحن نعمل بنشاط على جبهتين:
التكامل مع المحولات السريعة.
لدينا طلب سحب قيد التقدم للاستبدال HubApi مع وجه سريع المعانقة. سيؤدي هذا إلى توفير تنزيلات موثوقة للجميع باستخدام Swift-transformers وMLX-Swift-lm والنظام البيئي الأوسع. إذا كنت تحتفظ بمكتبة أو تطبيق قائم على Swift وتريد المساعدة في استخدام تقنية Swift-huggingface، فاتصل بنا — يسعدنا تقديم المساعدة.
تنزيلات أسرع مع Xet.
نحن نضيف دعمًا للواجهة الخلفية للتخزين Xet، والتي تتيح إلغاء البيانات المكررة المستندة إلى أجزاء وتنزيلات أسرع بشكل ملحوظ للنماذج الكبيرة. المزيد عن هذا قريبا.
جربه
أضف وجهًا سريعًا إلى مشروعك:
dependencies: [
.package(url: "https://github.com/huggingface/swift-huggingface.git", from: "0.4.0")
]
نحن نحب ملاحظاتك. إذا شعرت بالإحباط من تنزيلات النماذج في Swift، فجرّب ذلك وأخبرنا كيف ستسير الأمور. ستساعدنا تقارير تجربتك في تحديد أولويات ما يجب تحسينه بعد ذلك.
موارد
شكرًا لمجتمع Swift-Transformers على التعليقات التي شكلت هذا المشروع، ولكل من قدم مشكلات وشارك تجاربه. هذا لك. ❤️
