الكتابات/tutorial/2026/07
Tutorial17 يوليو 2026·30 دقيقة

دمج Kimi K3 مع TypeScript: بناء تطبيقات ذكاء اصطناعي بأكبر نموذج مفتوح في العالم

دليل عملي خطوة بخطوة لدمج Kimi K3 — نموذج Moonshot AI بـ 2.8 تريليون معامل وسياق مليون رمز — في تطبيقات TypeScript وNext.js. يشمل البث المباشر للتفكير، واستدعاء الأدوات، والمخرجات المنظمة، والرؤية البصرية.

بلغت النماذج مفتوحة الأوزان نقطة تحوّل حقيقية. حين أطلقت Moonshot AI نموذج Kimi K3 في يوليو 2026 — بـ 2.8 تريليون معامل إجمالي، ونحو 60-80 مليار معامل نشط لكل رمز عبر بنية Mixture-of-Experts، ونافذة سياق تبلغ مليون رمز — لم تكسر رقماً قياسياً في الحجم فحسب، بل أثبتت أن النماذج المفتوحة الكاملة قادرة على منافسة أفضل الأنظمة المغلقة في البرمجة والرياضيات والاستدلال على السياقات الطويلة في آنٍ واحد.

لمطوّري منطقة الشرق الأوسط وشمال أفريقيا وسائر مناطق العالم خارج الولايات المتحدة، هذا يُحدث فارقاً كبيراً. Kimi K3 متاح اليوم عبر واجهة برمجية متوافقة مع OpenAI، وقابل للاستضافة الذاتية على عناقيد GPU متعددة، ومُرخَّص بموجب رخصة مفتوحة الأوزان متسامحة. يأخذك هذا الدرس خطوةً بخطوة عبر دمج K3 في TypeScript: الإكمالات الأساسية، وبث رموز التفكير، واستدعاء الأدوات، والمخرجات المنظمة بصيغة JSON، والرؤية البصرية متعددة الوسائط — منتهياً بمسار API جاهز للإنتاج في Next.js 15.

إن كنت أكملت درس Kimi K2 من قبل، فالانتقال لا يتطلب سوى تغيير اسم النموذج وإضافة معامل reasoning_effort الجديد. نستعرض قائمة الترحيل في نهاية الدرس.

المتطلبات الأساسية

قبل البدء، تأكد من توفر:

  • Node.js 20+ (node --version)
  • TypeScript 5.4+
  • حساب في Moonshot AI ومفتاح API من لوحة التحكم
  • معرفة أساسية بـ async/await والأنماط المتوافقة مع OpenAI SDK

لا تحتاج إلى GPU — جميع الأمثلة تعمل عبر واجهة Moonshot المستضافة.

ما الذي ستبنيه

بنهاية هذا الدرس ستمتلك:

  1. عميلاً مُكتَّباً بالكامل لـ K3 يستخدم OpenAI SDK الرسمي
  2. دالة بث مباشر تفصل رموز التفكير عن الإجابات النهائية
  3. حلقة وكيل لاستدعاء الأدوات تُمكّن K3 من استدعاء دوال TypeScript
  4. مستخرج مخرجات منظمة يُعيد JSON صحيحاً ومُكتَّباً
  5. أداة رؤية بصرية لتحليل الصور
  6. مسار API في Next.js 15 يُغلّف K3 كتدفق أحداث خادم (SSE)

فهم Kimi K3

قبل كتابة الكود، إليك النموذج الذهني الذي يُشكّل كل قرار دمج.

بنية MoE. يمتلك Kimi K3 إجمالي 2.8 تريليون معامل، لكنه يُفعّل فقط نحو 60-80 مليار معامل لكل رمز عبر توجيه Mixture-of-Experts. استضافة النموذج تتطلب وحدات GPU متعددة من طراز A100/H100، لكن تكلفة الاستنتاج لكل رمز تظل تنافسية لأن الشريحة النشطة أصغر بكثير من 2.8 تريليون.

التفكير دائماً مُفعَّل. على خلاف K2، لا يتيح K3 تعطيل مرحلة التفكير. كل طلب يمر عبر سلسلة تفكير داخلية. تتحكم في عمق التفكير بمعامل reasoning_effort — القيمة المقبولة حالياً فقط "max"؛ ستُضيف Moonshot قيمتَي "medium" و"low" في إصدارات قادمة.

المعاملات ثابتة. معاملات مثل temperature وtop_p وn والعقوبات مُقيَّدة بالنموذج. لا ترسلها — يتجاهلها النموذج صامتاً.

نافذة سياق مليون رمز. نافذة السياق تبلغ مليون رمز مع تخزين مؤقت تلقائي للتعليمات. تغذية قاعدة كود تحتوي على 300,000 رمز في طلب واحد أمر عملي بمستوى تسعير K3.

واجهة برمجية متوافقة مع OpenAI. عنوان الخادم https://api.moonshot.ai/v1 — مطابق لـ K2. يمكنك أيضاً استخدام https://api.moonshot.ai/anthropic للواجهة بصيغة Anthropic (مفيد لإعدادات Claude Code وCline).

الخطوة 1: إعداد المشروع

mkdir kimi-k3-demo && cd kimi-k3-demo
npm init -y
npm install openai zod dotenv
npm install -D typescript @types/node tsx
npx tsc --init

عدّل tsconfig.json لاستهداف مخرجات ESM الحديثة:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "strict": true,
    "outDir": "dist",
    "esModuleInterop": true
  }
}

أنشئ ملف .env:

MOONSHOT_API_KEY=sk-your-key-here

وعميلاً مُكتَّباً في src/client.ts:

import OpenAI from "openai";
import "dotenv/config";
 
if (!process.env.MOONSHOT_API_KEY) {
  throw new Error("MOONSHOT_API_KEY غير موجود في متغيرات البيئة.");
}
 
export const kimi = new OpenAI({
  apiKey: process.env.MOONSHOT_API_KEY,
  baseURL: "https://api.moonshot.ai/v1",
});
 
export const K3 = "kimi-k3" as const;

هذا هو الملف الوحيد الذي تحتاج إلى تغييره عند تبديل المزودين — منطق الأعمال يبقى دون تعديل.

الخطوة 2: إكمال المحادثة الأساسي

تتضمن استجابات K3 حقل reasoning_content إلى جانب content المعتاد. أنشئ src/basic.ts لاسترداد الاثنين:

import { kimi, K3 } from "./client.js";
 
async function main() {
  const response = await kimi.chat.completions.create({
    model: K3,
    reasoning_effort: "max",   // خاص بـ K3؛ القيمة الوحيدة المقبولة حالياً
    messages: [
      {
        role: "user",
        content: "اشرح كيف يعمل توجيه Mixture-of-Experts في أقل من 100 كلمة.",
      },
    ],
    max_completion_tokens: 4096,
  } as any); // أنواع OpenAI SDK لا تتضمن reasoning_effort بعد
 
  const choice = response.choices[0];
  const reasoning = (choice.message as any).reasoning_content as string | null;
  const answer = choice.message.content;
 
  if (reasoning) {
    console.log("=== التفكير ===");
    console.log(reasoning);
    console.log();
  }
 
  console.log("=== الإجابة ===");
  console.log(answer);
}
 
main().catch(console.error);

نفّذ الأمر:

npx tsx src/basic.ts

ستشاهد سلسلة التفكير الداخلية لـ K3 مطبوعةً قبل الإجابة النهائية — أثر مرئي لكيفية وصوله إلى الاستنتاج.

الخطوة 3: البث المباشر مع رموز التفكير

يعرض البث المباشر التفكير والمحتوى كقناتَي دلتا منفصلتين. يتيح لك ذلك عرض مؤشر "جارٍ التفكير..." بينما يعالج النموذج، ثم الكشف عن الإجابة حين تكتمل.

أنشئ src/stream.ts:

import { kimi, K3 } from "./client.js";
 
async function streamK3(prompt: string): Promise<void> {
  const stream = await kimi.chat.completions.create({
    model: K3,
    reasoning_effort: "max",
    messages: [{ role: "user", content: prompt }],
    stream: true,
    max_completion_tokens: 8192,
  } as any);
 
  let inReasoning = false;
 
  for await (const chunk of stream) {
    const delta = chunk.choices[0]?.delta as any;
 
    if (delta?.reasoning_content) {
      if (!inReasoning) {
        process.stdout.write("\n[تفكير] ");
        inReasoning = true;
      }
      process.stdout.write(delta.reasoning_content);
    } else if (delta?.content) {
      if (inReasoning) {
        process.stdout.write("\n\n[إجابة] ");
        inReasoning = false;
      }
      process.stdout.write(delta.content);
    }
  }
 
  process.stdout.write("\n");
}
 
streamK3(
  "ما المقايضات بين بنيات المحولات الكثيفة والمتفرقة؟"
).catch(console.error);

النقطة الجوهرية: يُصدر K3 دلتا reasoning_content خلال مرحلة التفكير، ثم ينتقل إلى دلتا content للاستجابة النهائية. القناتان لا تتداخلان أبداً.

الخطوة 4: استدعاء الأدوات

يدعم K3 استدعاء الدوال بأسلوب OpenAI القياسي. مخطط الأداة ومعالجة الاستجابة مطابقان تماماً لما تكتبه مع GPT-4o، مما يجعل K3 بديلاً مباشراً في خطوط أنابيب استدعاء الأدوات.

أنشئ src/tools.ts:

import OpenAI from "openai";
import { kimi, K3 } from "./client.js";
 
const tools: OpenAI.Chat.Completions.ChatCompletionTool[] = [
  {
    type: "function",
    function: {
      name: "get_npm_downloads",
      description: "جلب عدد تنزيلات حزمة npm الأسبوعية",
      parameters: {
        type: "object",
        properties: {
          package_name: {
            type: "string",
            description: "اسم حزمة npm، مثل 'react'",
          },
        },
        required: ["package_name"],
      },
    },
  },
];
 
async function get_npm_downloads(packageName: string): Promise<string> {
  const mockData: Record<string, number> = {
    react: 28_000_000,
    next: 8_500_000,
    openai: 4_200_000,
  };
  const count = mockData[packageName] ?? 500_000;
  return `${packageName} حقّق ${count.toLocaleString("ar")} تنزيلاً الأسبوع الماضي.`;
}
 
async function runAgent(question: string): Promise<void> {
  const messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [
    { role: "user", content: question },
  ];
 
  for (let i = 0; i < 5; i++) {
    const response = await kimi.chat.completions.create({
      model: K3,
      reasoning_effort: "max",
      messages,
      tools,
      tool_choice: "auto",
      max_completion_tokens: 4096,
    } as any);
 
    const choice = response.choices[0];
    messages.push(choice.message as any);
 
    if (choice.finish_reason === "stop") {
      console.log("الإجابة النهائية:", choice.message.content);
      return;
    }
 
    if (choice.finish_reason === "tool_calls") {
      const toolCalls = choice.message.tool_calls ?? [];
      for (const call of toolCalls) {
        const args = JSON.parse(call.function.arguments) as { package_name: string };
        const result = await get_npm_downloads(args.package_name);
        console.log(`استدعاء أداة: ${call.function.name}(${args.package_name}) → ${result}`);
        messages.push({
          role: "tool",
          tool_call_id: call.id,
          content: result,
        });
      }
    }
  }
}
 
runAgent("قارن عدد تنزيلات npm الأسبوعية لكل من react وnext وopenai.").catch(console.error);

الخطوة 5: المخرجات المنظمة

يدعم K3 مخرجات JSON Schema المنظمة مع strict: true. مقترناً بـ Zod لسلامة الأنواع في TypeScript، ينتج ذلك استجابات صحيحة ومُكتَّبة بالكامل دون أي مخاطر في التحليل اليدوي.

أنشئ src/structured.ts:

import { kimi, K3 } from "./client.js";
import { z } from "zod";
 
const codeReviewSchema = z.object({
  overall_score: z.number().min(1).max(10),
  issues: z.array(
    z.object({
      severity: z.enum(["critical", "warning", "suggestion"]),
      line: z.number().optional(),
      description: z.string(),
      fix: z.string(),
    })
  ),
  summary: z.string(),
});
 
type CodeReview = z.infer<typeof codeReviewSchema>;
 
async function reviewCode(code: string): Promise<CodeReview> {
  const response = await kimi.chat.completions.create({
    model: K3,
    reasoning_effort: "max",
    messages: [
      {
        role: "system",
        content: "أنت مراجع كود TypeScript أول. أعد JSON منظماً فقط.",
      },
      {
        role: "user",
        content: `راجع هذا الكود:\n\n\`\`\`typescript\n${code}\n\`\`\``,
      },
    ],
    response_format: {
      type: "json_schema",
      json_schema: {
        name: "code_review",
        strict: true,
        schema: {
          type: "object",
          properties: {
            overall_score: { type: "number" },
            issues: {
              type: "array",
              items: {
                type: "object",
                properties: {
                  severity: {
                    type: "string",
                    enum: ["critical", "warning", "suggestion"],
                  },
                  line: { type: "number" },
                  description: { type: "string" },
                  fix: { type: "string" },
                },
                required: ["severity", "description", "fix"],
              },
            },
            summary: { type: "string" },
          },
          required: ["overall_score", "issues", "summary"],
        },
      },
    },
    max_completion_tokens: 4096,
  } as any);
 
  const raw = response.choices[0].message.content ?? "{}";
  return codeReviewSchema.parse(JSON.parse(raw));
}
 
const sampleCode = `
async function fetchUser(id: string) {
  const res = await fetch('/api/users/' + id)
  const data = await res.json()
  return data.user
}
`;
 
reviewCode(sampleCode)
  .then((review) => {
    console.log(`التقييم: ${review.overall_score}/10`);
    review.issues.forEach((issue) => {
      console.log(`[${issue.severity}] ${issue.description}`);
      console.log(`  الإصلاح: ${issue.fix}`);
    });
    console.log(`الملخص: ${review.summary}`);
  })
  .catch(console.error);

يضمن strict: true أن K3 يلتزم بالمخطط تماماً — لا خصائص إضافية، ولا حقول مطلوبة مفقودة.

الخطوة 6: الرؤية البصرية — تحليل الصور

يقبل K3 الصور كـ data URI مُرمَّز بـ base64 أو عبر نظام مرجع ملفات ms:// الخاص بـ Moonshot. للتحليل الفردي، المسار الأبسط هو base64.

أنشئ src/vision.ts:

import { kimi, K3 } from "./client.js";
import { readFileSync } from "fs";
import path from "path";
 
async function analyseImage(imagePath: string, question: string): Promise<string> {
  const buffer = readFileSync(imagePath);
  const base64 = buffer.toString("base64");
  const ext = path.extname(imagePath).slice(1);
  const mimeType = ext === "jpg" ? "image/jpeg" : `image/${ext}`;
 
  const response = await kimi.chat.completions.create({
    model: K3,
    reasoning_effort: "max",
    messages: [
      {
        role: "user",
        content: [
          {
            type: "image_url",
            image_url: { url: `data:${mimeType};base64,${base64}` },
          },
          { type: "text", text: question },
        ],
      },
    ],
    max_completion_tokens: 2048,
  } as any);
 
  return response.choices[0].message.content ?? "";
}
 
export { analyseImage };

مثال على الاستخدام:

import { analyseImage } from "./vision.js";
 
const result = await analyseImage(
  "./screenshot.png",
  "صف واجهة المستخدم واذكر أي مشكلات في إمكانية الوصول تلاحظها."
);
console.log(result);

يدعم K3 صيغ JPEG وPNG وWebP وGIF عبر base64. للصور الكبيرة أو الرفع المتكرر، استخدم Files API الخاصة بـ Moonshot للحصول على مرجع ms:// بدلاً من إعادة رفع البيانات في كل طلب.

الخطوة 7: مسار API في Next.js 15

غلّف بث K3 في مسار App Router في Next.js للاستخدام الإنتاجي. يُعيد المسار القناتين (التفكير والمحتوى) كأحداث خادم (SSE).

app/api/kimi-k3/route.ts:

import { NextRequest } from "next/server";
import OpenAI from "openai";
 
const kimi = new OpenAI({
  apiKey: process.env.MOONSHOT_API_KEY!,
  baseURL: "https://api.moonshot.ai/v1",
});
 
export async function POST(request: NextRequest) {
  const { messages } = (await request.json()) as {
    messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[];
  };
 
  const stream = await kimi.chat.completions.create({
    model: "kimi-k3",
    reasoning_effort: "max",
    messages,
    stream: true,
    max_completion_tokens: 16384,
  } as any);
 
  const encoder = new TextEncoder();
 
  return new Response(
    new ReadableStream({
      async start(controller) {
        try {
          for await (const chunk of stream) {
            const delta = chunk.choices[0]?.delta as any;
            const data = {
              reasoning: delta?.reasoning_content ?? null,
              content: delta?.content ?? null,
            };
            controller.enqueue(
              encoder.encode(`data: ${JSON.stringify(data)}\n\n`)
            );
          }
          controller.enqueue(encoder.encode("data: [DONE]\n\n"));
          controller.close();
        } catch (err) {
          controller.error(err);
        }
      },
    }),
    {
      headers: {
        "Content-Type": "text/event-stream",
        "Cache-Control": "no-cache",
        Connection: "keep-alive",
      },
    }
  );
}

المستهلك على جانب العميل:

async function streamK3Chat(
  userMessage: string,
  onChunk: (text: string, isReasoning: boolean) => void
) {
  const res = await fetch("/api/kimi-k3", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      messages: [{ role: "user", content: userMessage }],
    }),
  });
 
  const reader = res.body?.getReader();
  const decoder = new TextDecoder();
  if (!reader) return;
 
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
 
    const lines = decoder.decode(value).split("\n").filter((l) => l.startsWith("data: "));
    for (const line of lines) {
      const payload = line.slice(6);
      if (payload === "[DONE]") return;
      const parsed = JSON.parse(payload) as {
        reasoning: string | null;
        content: string | null;
      };
      if (parsed.reasoning) onChunk(parsed.reasoning, true);
      if (parsed.content) onChunk(parsed.content, false);
    }
  }
}

في مكوّن React الخاص بك، مرّر setters حالة منفصلة لـ reasoning وcontent إلى onChunk لعرضهما في لوحتين منفصلتين — لوحة تفكير قابلة للطي ومربع إجابة نهائية.

الانتقال من Kimi K2

إن كان لديك كود موجود من درس K2، فالانتقال بسيط:

التغييرK2K3
معرّف النموذجkimi-k2kimi-k3
معامل التفكيرthinking: { type: "enabled", budget_tokens: N }reasoning_effort: "max"
نافذة السياق128 ألف رمزمليون رمز
درجة الحرارةقابلة للضبطثابتة — لا ترسلها
الرؤية البصريةغير مدعوممدعوم عبر base64 / ms://
حقل بث التفكيرغير موجوددلتا reasoning_content

عنوان الخادم (https://api.moonshot.ai/v1) وترويسة المصادقة لا يتغيران.

استكشاف الأخطاء وإصلاحها

"Invalid parameter: temperature" — لا يقبل K3 معاملات أخذ العينات. أزل temperature وtop_p وn وحقول العقوبات من طلباتك.

reasoning_content فارغ — تأكد من تمرير reasoning_effort: "max" وإضافة as any للطلب حتى تتحقق أنواع OpenAI SDK من K3.

السياق يتجاوز الحد — يقبل K3 ما يصل إلى مليون رمز إدخال، لكن max_completion_tokens يبلغ افتراضياً 131,072 رمز. للمخرجات الطويلة جداً، حدّد قيمته صراحةً حتى 1,048,576.

البث ينقطع مبكراً — مهام الاستدلال المعقدة تُولّد سلاسل تفكير طويلة قبل الإجابة النهائية. ارفع max_completion_tokens إن بدت المخرجات مقطوعة.

فشل التحقق من المخرجات المنظمة — تأكد من أن JSON Schema تستخدم فقط الأنواع المدعومة في الوضع الصارم لـ K3: object وarray وstring وnumber وboolean وnull.

الخطوات التالية

  • غذّ مستودعاً بالكامل إلى K3 باستخدام نافذة سياق مليون رمز واطلب مراجعة معمارية شاملة — أمر مستحيل مع نماذج 128K رمز
  • ادمج الرؤية البصرية مع تحويل PDF إلى صور لبناء خطوط أنابيب مراجعة المستندات
  • جرّب نقطة النهاية المتوافقة مع Anthropic (https://api.moonshot.ai/anthropic) لاستخدام K3 داخل Claude Code عبر تعيين ANTHROPIC_BASE_URL=https://api.moonshot.ai/anthropic
  • قارن عمق استدلال K3 مع Claude Fable 5 على مهام البرمجة الطويلة الأفق

الخلاصة

Kimi K3 هو أكبر نموذج مفتوح المصدر متاح اعتباراً من يوليو 2026، وواجهته البرمجية المتوافقة مع OpenAI تعني إمكانية دمجه في أي مشروع TypeScript أو Next.js بأقل احتكاك ممكن. الإضافات الرئيسية مقارنةً بـ K2 هي معامل reasoning_effort الذي يكشف سلسلة التفكير المدمجة، وقناة بث reasoning_content المنفصلة، ودعم الرؤية البصرية الأصلي، ونافذة سياق مليون رمز تستوعب قواعد الكود الكاملة في طلب واحد. ابدأ بالعميل المُكتَّب أعلاه، أضف البث المباشر للواجهات التي يراها المستخدمون، وتوجّه للمخرجات المنظمة كلما احتجت إلى استجابات قابلة للقراءة آلياً من نظام ذكاء اصطناعي استدلالي.