سير عمل دعم Next.js لخلفيات OpenAI

Share:

شرح عملي

أنشئ سير عمل دعم في Next.js لخلفية OpenAI

أنشئ واجهة مركّزة لاستقبال ومراجعة طلبات دعم العملاء باستخدام Next.js App Router وTypeScript وحدود مسار على الخادم، جاهزة للربط بخدمة AI تم التحقق منها بشكل مستقل.

إعداد فريقي التحرير والهندسة في بوابة الذكاء الاصطناعي، GateOfAI, LLC.

ما الذي ينشئه هذا الشرح العملي المتحقق منه؟

ينشئ هذا الشرح تطبيقاً صغيراً لسير عمل الدعم باستخدام Next.js وReact. يمكن لموظف الدعم إدخال رسالة عميل، واختيار فئة الدعم، وتحديد أسلوب الرد، ثم إرسال الطلب إلى مسار على الخادم ومراجعة النتيجة الموحّدة. ويظل المشروع المكتمل مفيداً عن قصد، من دون الادعاء بأن نموذجاً لغوياً متصل به حين لا يكون عقد المزوّد قد تم التحقق منه.

يدعم السياق المتحقق منه استخدام Next.js بوصفه إطار React لبناء تطبيقات ويب حديثة. ويشمل قدرات مثل App Router والعرض من جهة الخادم والتوليد الثابت ومسارات API ودعم TypeScript وتحسين الصور. يستخدم هذا الدليل App Router ومعالج المسار لأنهما يوفران فصلاً واضحاً بين واجهة تفاعلية في المتصفح ومنطق التطبيق على الخادم.

يصف السياق المتحقق منه حول OpenAI أيضاً مثالاً من OpenAI DevDay، جرى فيه ربط خادم FastAPI بواجهة Next.js أمامية. ويحمل هذا المثال درساً معمارياً مهماً: إذ يمكن لواجهة Next.js العمل مع خدمة Backend مخصصة. لكنه لا يتحقق من SDK JavaScript محدد من OpenAI، أو اسم نموذج، أو endpoint، أو parameter، أو schema للاستجابة، أو سعر، أو حصة استخدام. ولهذا السبب، ينشئ هذا المقال حدود تكامل موثوقة بدلاً من نشر كود غير متحقق منه خاص بالمزوّد.

والنتيجة هي أساس لمنتج دعم: نموذج في المتصفح، وعقد طلبات مكتوب الأنواع، ومسار على الخادم، وبنية استجابة متوقعة، ولوحة مراجعة. وبعد أن تتحقق مؤسستك من وثائق OpenAI API الحالية ومتطلبات التعامل مع بيانات العملاء لديها، يمكن استبدال مسار العينة بمحوّل من جهة الخادم يستدعي خدمة المزوّد المعتمدة.

المتطلبات المسبقة

  • تثبيت حديث لإصدار Node.js LTS وnpm.
  • إلمام أساسي بمكوّنات React وTypeScript وسطر الأوامر.
  • مشروع Next.js جديد أُنشئ مع تفعيل TypeScript وApp Router.
  • محرر كود قادر على تحرير ملفات TypeScript وTSX.
  • رسائل دعم تجريبية غير حساسة للاختبار المحلي.

لا تستخدم كلمات مرور حقيقية أو رموز وصول أو بيانات بطاقات دفع أو سجلات عملاء سرية في عرض توضيحي محلي. يعالج هذا الشرح نصوصاً تجريبية فقط. يحتاج سير عمل الدعم في بيئة الإنتاج إلى عمليات معتمدة خاصة به للتعامل مع البيانات والاحتفاظ بها والتحكم في الوصول والمراجعة.

الخطوة ١: إنشاء مشروع Next.js

أنشئ تطبيقاً جديداً باستخدام مولّد مشاريع Next.js الحالي. اختر TypeScript وApp Router عند ظهور المطالبات. قد تتغير مطالبات المولّد الدقيقة بين الإصدارات، لذا راجعها قبل تأكيد اختياراتك.

npx create-next-app@latest nextjs-support-workflow
cd nextjs-support-workflow
npm run dev

افتح http://localhost:3000 بعد تشغيل خادم التطوير. يوفر Next.js بنية تطبيق قائمة على الملفات. في هذا الشرح، تُعرض الصفحة الرئيسية من src/app/page.tsx، بينما يُنفذ endpoint الخادم في src/app/api/support-request/route.ts.

حافظ على نطاق التطبيق الأولي محدوداً. لا تحتاج واجهة الدعم إلى مصادقة، أو قاعدة بيانات للعملاء، أو مزود AI، أو تكامل CRM، أو إرسال تلقائي من أجل التحقق من سير العمل الأول. ابدأ بجعل تجربة الطلب والمراجعة واضحة، ثم أضف قدرات اختُبرت بشكل مستقل واحدة تلو الأخرى.

الخطوة ٢: تحديد عقد دعم مشترك

تستفيد واجهة الدعم من عقد مستقر بين المتصفح والخادم. يوفر TypeScript ملاحظات أثناء وقت الترجمة، لكن معالج المسار ما زال يتحقق من القيم الواردة وقت التشغيل. المتصفح ليس نقطة فرض موثوقة: إذ يمكن للمستخدم تعديل قيم النموذج أو إرسال طلب مباشرة إلى المسار.

أنشئ src/lib/support.ts:

export const productAreas = [
  "Billing",
  "Account access",
  "Technical issue",
  "General question",
] as const;

export const tones = ["Warm", "Concise", "Formal"] as const;

export type ProductArea = (typeof productAreas)[number];
export type Tone = (typeof tones)[number];

export type SupportRequest = {
  ticket: string;
  productArea: ProductArea;
  tone: Tone;
};

export type SupportReview = {
  received: boolean;
  ticketLength: number;
  productArea: ProductArea;
  tone: Tone;
  nextStep: string;
};

export function isProductArea(value: unknown): value is ProductArea {
  return typeof value === "string" && productAreas.includes(value as ProductArea);
}

export function isTone(value: unknown): value is Tone {
  return typeof value === "string" && tones.includes(value as Tone);
}

export function parseSupportRequest(value: unknown): SupportRequest | null {
  if (!value || typeof value !== "object") return null;

  const input = value as Record<string, unknown>;
  const ticket = typeof input.ticket === "string" ? input.ticket.trim() : "";

  if (ticket.length < 20 || ticket.length > 8000) return null;
  if (!isProductArea(input.productArea) || !isTone(input.tone)) return null;

  return { ticket, productArea: input.productArea, tone: input.tone };
}

يوفّر هذا الموديول للنموذج ومعالج المسار مفردات مشتركة. يتضمن الطلب نص التذكرة وفئة محدودة وخياراً محدوداً للنبرة. أما الاستجابة فهي تشغيلية عمداً وليست مولّدة بالـAI: فهي تؤكد الاستلام، وتسجل طول النص، وتكرر الخيارات المحددة، وتوفر رسالة بالخطوة التالية. وهذا يجعل التطبيق قابلاً للاختبار من دون تقديم محتوى محاكى على أنه إجابة من AI.

يمثل النطاق من ٢٠ إلى ٨٬٠٠٠ حرف قراراً خاصاً بالمنتج في هذه العينة، وليس حداً من OpenAI. عدّله بعد تقييم أنواع الرسائل التي يتلقاها فريق الدعم لديك وقيود أي خدمة Backend معتمدة.

الخطوة ٣: إضافة معالج مسار الخادم

توفر معالجات المسارات حدود HTTP من جهة الخادم في مشروع App Router. أنشئ src/app/api/support-request/route.ts:

import { NextRequest } from "next/server";
import {
  parseSupportRequest,
  type SupportReview,
} from "@/lib/support";

export async function POST(request: NextRequest) {
  let body: unknown;

  try {
    body = await request.json();
  } catch {
    return Response.json(
      { error: "Send a valid JSON request body." },
      { status: 400 },
    );
  }

  const input = parseSupportRequest(body);

  if (!input) {
    return Response.json(
      {
        error:
          "Enter 20 to 8,000 characters and select a supported product area and tone.",
      },
      { status: 400 },
    );
  }

  const review: SupportReview = {
    received: true,
    ticketLength: input.ticket.length,
    productArea: input.productArea,
    tone: input.tone,
    nextStep:
      "Request accepted for human review. Connect an approved server-side AI adapter only after its provider contract is verified.",
  };

  return Response.json({ review }, { status: 200 });
}

يحلل المسار JSON ويتحقق منه باستخدام المساعد المشترك، ثم يعيد إما استجابة 400 مضبوطة أو كائن مراجعة مستقر. وتبقى هذه قيمة مهمة حتى قبل إدخال AI: فالمتصفح لديه عقد محدد، ولا يمكن للطلبات المباشرة تجاوز فحوصات الإدخال على الخادم.

عند اعتماد تكامل مع مزوّد، استبدل إنشاء review باستدعاء محوّل يتحكم به الخادم. لا تضع بيانات اعتماد المزوّد في كود المتصفح أو في متغيرات مكشوفة للعميل عمداً. افصل محوّل الطلبات عن مكوّن الصفحة كي يمكن مراجعة سلوكه ومعالجة أخطائه وسياسة التسجيل والاختبارات الخاصة به بشكل مستقل.

إذا كان منتجك المستقبلي تطبيق ChatGPT بدلاً من تطبيق ويب تقليدي، فضع في الاعتبار إرشادات OpenAI الرسمية التي تفيد بأن التطبيقات تعمل داخل iframe متداخلة مرتين وقد تخضع لسياسات Content Security Policy صارمة. قد تتصرف الواجهة المحلية بصورة مختلفة عن تكامل iframe المنشور، لذا تحقق من بيئة النشر النهائية مبكراً.

الخطوة ٤: بناء نموذج الدعم من جهة العميل

أنشئ src/components/support-workflow.tsx. هذا المكوّن هو مكوّن عميل لأنه يعالج أحداث النموذج وحالة المتصفح.

"use client";

import { FormEvent, useState } from "react";
import {
  productAreas,
  tones,
  type SupportReview,
} from "@/lib/support";

type FormState = {
  ticket: string;
  productArea: (typeof productAreas)[number];
  tone: (typeof tones)[number];
};

const initialForm: FormState = {
  ticket: "",
  productArea: "General question",
  tone: "Warm",
};

export function SupportWorkflow() {
  const [form, setForm] = useState<FormState>(initialForm);
  const [review, setReview] = useState<SupportReview | null>(null);
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(false);

  async function submit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setError("");
    setReview(null);

    if (form.ticket.trim().length < 20) {
      setError("Enter at least 20 characters of ticket text.");
      return;
    }

    setLoading(true);

    try {
      const response = await fetch("/api/support-request", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(form),
      });

      const payload: unknown = await response.json();

      if (!response.ok || !payload || typeof payload !== "object" || !("review" in payload)) {
        const message =
          payload && typeof payload === "object" && "error" in payload
            ? String(payload.error)
            : "The server could not process this request.";
        throw new Error(message);
      }

      setReview(payload.review as SupportReview);
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "Unexpected request failure.");
    } finally {
      setLoading(false);
    }
  }

  return (
    <section>
      <form onSubmit={submit}>
        <label htmlFor="ticket">Customer message</label>
        <textarea
          id="ticket"
          value={form.ticket}
          onChange={(event) => setForm((current) => ({ ...current, ticket: event.target.value }))}
          minLength={20}
          maxLength={8000}
          rows={10}
          required
        />

        <label htmlFor="productArea">Product area</label>
        <select
          id="productArea"
          value={form.productArea}
          onChange={(event) => setForm((current) => ({
            ...current,
            productArea: event.target.value as FormState["productArea"],
          }))}
        >
          {productAreas.map((area) => <option key={area}>{area}</option>)}
        </select>

        <label htmlFor="tone">Requested reply style</label>
        <select
          id="tone"
          value={form.tone}
          onChange={(event) => setForm((current) => ({
            ...current,
            tone: event.target.value as FormState["tone"],
          }))}
        >
          {tones.map((tone) => <option key={tone}>{tone}</option>)}
        </select>

        {error ? <p role="alert">{error}</p> : null}
        <button type="submit" disabled={loading}>
          {loading ? "Submitting…" : "Submit for review"}
        </button>
      </form>

      <aside aria-live="polite">
        <h2>Review status</h2>
        {review ? (
          <ul>
            <li>Received: {review.received ? "Yes" : "No"}</li>
            <li>Characters received: {review.ticketLength}</li>
            <li>Product area: {review.productArea}</li>
            <li>Requested style: {review.tone}</li>
            <li>Next step: {review.nextStep}</li>
          </ul>
        ) : (
          <p>Submit a non-sensitive example to test the server contract.</p>
        )}
      </aside>
    </section>
  );
}

يتحقق المكوّن من طول التذكرة لتقديم ملاحظات سريعة، بينما يعيد المسار التحقق بغرض الفرض. وبعد الطلب غير المتزامن، لا يحدّث المكوّن حالته إلا من الاستجابة المستلمة. وتستخدم لوحة المراجعة aria-live كي تتمكن التقنيات المساعدة من الإعلان عن تغييرات الحالة.

الخطوة ٥: عرض سير العمل من صفحة App Router

استبدل محتوى src/app/page.tsx بما يلي:

import { SupportWorkflow } from "@/components/support-workflow";

export default function HomePage() {
  return (
    <main>
      <h1>Support Workflow Review</h1>
      <p>
        A Next.js App Router example with a typed browser-to-server support request.
      </p>
      <SupportWorkflow />
    </main>
  );
}

شغّل خادم التطوير وأرسل رسالة تجريبية تتجاوز ٢٠ حرفاً. يفترض أن تتلقى نتيجة مراجعة موحدة. ثم اختبر الإدخال غير الصالح، بما في ذلك رسالة قصيرة أو طلب بفئة غير مدعومة، للتأكد من أن المسار يعيد خطأً مضبوطاً.

الاختبار وقرارات الإنتاج

قبل ربط خدمة AI، اختبر الأجزاء الحتمية من النظام. تأكد من أن الإدخال الصالح يتلقى استجابة 200، وأن JSON المشوه يتلقى استجابة 400، وأن قيم الفئات غير المدعومة تُرفض، وأن المتصفح يعرض خطأً مفيداً. هذه الفحوصات مستقلة عن أي نموذج وتظل قيّمة بعد إضافة محوّل AI.

curl -i -X POST http://localhost:3000/api/support-request 
  -H "Content-Type: application/json" 
  -d '{"ticket":"I need help understanding a duplicate billing entry on my example account.","productArea":"Billing","tone":"Warm"}'

ينبغي أن يحتوي محوّل المزوّد المستقبلي على اختبارات صريحة لبناء الطلبات وتحليل الاستجابات وسلوك انتهاء المهلة ورسائل الأخطاء الآمنة. لا تختبر سير عمل الدعم بمجرد التحقق مما إذا كان ينتج نصاً مقنعاً. اختبر ما إذا كان التطبيق يحافظ على الفئة المحددة، ويتعامل مع الإخفاقات بصورة متوقعة، ويبقي بيانات الاعتماد الحساسة على الخادم، ويتطلب مراجعة بشرية قبل إرسال أي تواصل مؤثر.

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

ما الذي تضيفه بعد التحقق من API؟

  • محوّل AI معتمد من جهة الخادم، مع مراجعة وثائق المزوّد وقت التنفيذ.
  • عقد مخرجات محدود ومتحقق منه يناسب عملية الدعم لديك.
  • هوية موثقة للمستخدم والمؤسسة لضوابط الطلبات.
  • قائمة انتظار للموافقة البشرية بدلاً من الإرسال التلقائي الموجّه للعملاء.
  • استرجاع سياسات واعٍ بالمصادر فقط بعد تحديد ملكية السياسات وآلية التعامل مع البيانات.
  • اختبارات نشر لقيود Content Security Policy إذا كان المنتج سيعمل كتطبيق ChatGPT.

الدرس العملي مباشر: يوفر Next.js أساساً قوياً لتطبيقات React، بينما ينبغي التعامل مع مزوّد AI باعتباره تبعية منفصلة من جهة الخادم تستلزم التحقق. أسّس سير عمل الدعم وحدوده أولاً، ثم ادمج خدمة AI المعتمدة بالاعتماد على الوثائق الرسمية الحالية والاختبارات المركّزة والمساءلة البشرية.

المصادر

Share:
تنسيق الوكلاء المستقلين أتمتة العمليات التشغيلية المعقدة

هل تحتاج إلى وكلاء ذكاء اصطناعي لأتمتة عمليات مؤسستك؟

صمم شبكات وكلاء متعدّدة ذاتية التشغيل لاتخاذ القرارات وأتمتة المهام الشاقة مع آليات رقابة وحوكمة بشرية صارمة (Human-in-the-Loop) بدون هدر في التوكنات، مع ضمان تسليم المراحل.

اطرح مشروعك واحصل على عروض مخصصة
تبحث عن حلول أتمتة ووكلاء جاهزين للتشغيل فوراً؟ استكشف حلول الأتمتة الجاهزة ←
حماية اتفاقية عدم الإفصاح (NDA)
عروض معتمدة خلال 24-48 ساعة
استشارة وتحديد نطاق مجاناً (0$ مقدماً)

هل كان هذا الشرح مفيداً؟

هل لديك سؤال حول هذا الشرح؟

مساعدنا الذكي قرأ هذا الشرح وهو جاهز للإجابة على استفساراتك المعمارية والبرمجية فوراً.

🤖
مرحباً بك! يمكنك سؤالي عن أي كود أو مفهوم تقني ورد في هذا الشرح.
مساعد الذكاء الاصطناعي متاح مجاناً للمهندسين والمشتركين.
تسجيل دخول مجاني لبدء المحادثة
🛡️ سوق حلول الإنتاج المؤسسية (0% عمولة رموز BYOK)

أنظمة وأكواد جاهزة للتشغيل مرتبطة بهذا الموضوع

تصفح سوق الحلول بالكامل →
أدوات المطورين • BYOK 🛡️ من $14/شهرياً

معماري أوامر المطورين والوكلاء (BYOK)

بيئة هندسية لبناء أوامر النظام (System Prompts)، قوالب LangGraph و CrewAI، مع دعم مفاتيح BYOK الخاصة بك.

مشروع مخصص • ضمان Escrow 🛡️ عرض سعر مخصص

بناء أنظمة ذكاء اصطناعي مخصصة (Escrow)

تعاقد مع مهندسي ذكاء اصطناعي معتمدين لبناء أو تخصيص أنظمة RAG ووكلاء بمفاتيح BYOK تحت حماية الضمان المالي.

Custom Chatbots • BYOK $1,187

SkillForge AI – AI-Powered Learning Management System

An AI-powered learning platform for discovering courses, generating learning content, managing students and instructors, and delivering a complete…

مرشد بوابة الذكاء الاصطناعي
نشط للخدمة
مرحباً بك في بوابة الذكاء الاصطناعي! أنا مرشدك هنا لمساعدتك في فهم خدمات المنصة، باقات التشغيل وخطط الضمان المالي. كيف يمكنني إرشادك اليوم؟