بناء ذكاء اصطناعي محادثاتي باستخدام Claude وChatGPT APIs: دليل عملي

Share:
درس تقني
متوسط
⏱ ٣٥ دقيقة قراءة
© بوابة الذكاء الاصطناعي ٢٠٢٦-٠٦-٠٢

تصميم بوابة LLM متعددة المزودين في Next.js باستخدام معالجات مسار App Router للتبديل الديناميكي بين طلبات الإنتاج بين معماريات OpenAI وAnthropic مع الحفاظ على سياق الحالة.

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

  • Node.js ١٨.x أو أعلى
  • Next.js ١٤.x أو ١٥.x (هيكل App Router)
  • مفاتيح API صالحة تم تكوينها في وحدات تحكم المطورين لـ OpenAI وAnthropic
  • الإلمام بحمولات API متعددة الأشكال وتكوين حالة React

ما الذي نبنيه

غالبًا ما تتطلب هندسة الذكاء الاصطناعي في الإنتاج تكرار النماذج أو التوجيه المتخصص — توجيه المهام الإبداعية إلى Claude والتحديثات الهيكلية الصارمة إلى GPT. في هذا الدليل، نبني طبقة تجريد API موحدة تقوم بتنظيف وتخطيط وتنفيذ المحادثات متعددة الأدوار عبر كلا النظامين بشكل نظيف.

الإعداد والتثبيت

ابدأ طبقة تطبيق Next.js نظيفة وقم بتنزيل حزم SDK الرسمية لكلا البائعين:


npx create-next-app@latest multi-provider-chat --ts --no-tailwind --app --src-dir=false
cd multi-provider-chat
npm install openai @anthropic-ai/sdk
  

املأ مصفوفة البيئة المحلية الخاصة بك داخل .env.local في دليل الجذر الخاص بك:


OPENAI_API_KEY=your_openai_project_secret_key
ANTHROPIC_API_KEY=your_anthropic_live_secret_key
  

الخطوة ١: هندسة بوابة النموذج الموحدة

قم بإنشاء معالج مسار الخادم الخاص بك في app/api/chat/route.js. نقوم بإنشاء كلا العميلين بشكل صريح وننشئ محلل تجريد للتعامل مع اختلافات التخطيط الهيكلي بين مصفوفة الخيارات الخاصة بـ OpenAI وكتل المحتوى الخاصة بـ Anthropic.


import { NextResponse } from 'next/server';
import { OpenAI } from 'openai';
import { Anthropic } from '@anthropic-ai/sdk';

const openai = new OpenAI();
const anthropic = new Anthropic();

export async function POST(req) {
    try {
        const { provider, messages } = await req.json();

        if (!messages || !Array.isArray(messages)) {
            return NextResponse.json({ error: 'Malformed message history payload' }, { status: 400 });
        }

        let replyText = '';

        if (provider === 'openai') {
            const response = await openai.chat.completions.create({
                model: 'gpt-4o-mini',
                messages: messages.map(msg => ({
                    role: msg.role,
                    content: msg.content
                }))
            });
            replyText = response.choices[0].message.content;

        } else if (provider === 'anthropic') {
            // Anthropic separates the 'system' message from the historical array
            const systemMessage = messages.find(m => m.role === 'system')?.content || 'You are a precise assistant.';
            const conversationHistory = messages.filter(m => m.role !== 'system');

            const response = await anthropic.messages.create({
                model: 'claude-3-5-haiku-20241022',
                max_tokens: 1024,
                system: systemMessage,
                messages: conversationHistory.map(msg => ({
                    role: msg.role === 'assistant' ? 'assistant' : 'user', // Safe role mapping
                    content: msg.content
                }))
            });
            replyText = response.content[0].text;
            
        } else {
            return NextResponse.json({ error: 'Unsupported provider routing request' }, { status: 400 });
        }

        return NextResponse.json({ reply: replyText });

    } catch (error) {
        console.error('Gateway Route Exception:', error);
        return NextResponse.json({ error: error.message || 'Internal processing error' }, { status: 500 });
    }
}
  

الخطوة ٢: بناء مكون الواجهة متعددة الأشكال

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


'use client';
import { useState } from 'react';

export default function HomeChatWorkspace() {
    const [messages, setMessages] = useState([
        { role: 'system', content: 'You are a helpful software engineering consultant.' }
    ]);
    const [input, setInput] = useState('');
    const [provider, setProvider] = useState('openai'); // Default routing value
    const [isLoading, setIsLoading] = useState(false);

    const handleFormSubmit = async (e) => {
        e.preventDefault();
        if (!input.trim() || isLoading) return;

        const incomingUserNode = { role: 'user', content: input };
        setInput('');
        setIsLoading(true);

        // Update UI state with user message immediately
        const updatedHistory = [...messages, incomingUserNode];
        setMessages(updatedHistory);

        try {
            const response = await fetch('/api/chat', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ provider, messages: updatedHistory })
            });

            const data = await response.json();
            if (!response.ok) throw new Error(data.error || 'Server rejected request');

            setMessages((prev) => [...prev, { role: 'assistant', content: data.reply }]);
        } catch (err) {
            console.error('Inference Error:', err);
            setMessages((prev) => [...prev, { role: 'system', content: `Error: ${err.message}` }]);
        } finally {
            setIsLoading(false);
        }
    };

    return (
        

لوحة التحكم متعددة النماذج

setProvider(e.target.value)} disabled={isLoading}> المحرك: GPT-4o-Mini المحرك: Claude-3.5-Haiku
{messages.filter(m => m.role !== 'system').map((msg, idx) => (
{msg.role === 'user' ? 'أنت' : 'الذكاء الاصطناعي'}: {msg.content}
))}
setInput(e.target.value)} placeholder="اطرح سؤالاً تقنيًا..." disabled={isLoading} style={{ flex: 1, padding: '10px', borderRadius: '4px', border: '1px solid #ccc' }} />
); }
⚠️ تحذير متقدم من الإدخال: تفرض واجهة برمجة التطبيقات للرسائل الخاصة بـ Anthropic تناوبًا صارمًا للمصفوفة. إذا قمت بتمرير رسائل متتالية بنفس الدور (مثل 'user' متبوعًا بعقدة 'user' أخرى)، فسيرفض SDK الحمولة مع خطأ تحقق ٤٠٠. تأكد دائمًا من أن خط أنابيب التعيين الخاص بك ينظف تسلسلات بنية المصفوفة قبل إرسال التحديثات إلى محرك Claude.

اختبار محرك التوجيه الخاص بك

قم بتشغيل مساحة عمل تطبيق Next.js محليًا:

npm run dev

افتح http://localhost:3000. اختر **GPT-4o-Mini** واطرح سؤالاً. ثم قم بتبديل الخيار المنسدل إلى **Claude-3.5-Haiku** واطرح أسئلة متابعة مثل “هل يمكنك إعادة صياغة سؤالي الأخير بلغة Rust؟” لاحظ كيف أن مصفوفة السياق المستمرة ترسم بأمان بغض النظر عن تبديلات التبديل الخاصة بك.

ما الذي يجب بناؤه بعد ذلك

  • تحويل النظام لاستخدام أجزاء البث بشكل متزامن عبر كلا المكونين باستخدام أغلفة ReadableStream.
  • تنفيذ تسجيل مقارنة النماذج الآلي لقياس تباينات زمن التنفيذ بين موجهات OpenAI وAnthropic.
  • إضافة كتلة منطقية تمريرية تقوم بتبديل المزودين تلقائيًا إذا واجه أحد البائعين خطأ ٥٠٣ في حد المعدل.

Share:

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