112797

۳ روش برای اتصال چندین API به هم کدامند؟

APIها بلوک‌های ساختمانی قابل ترکیب وب مدرن هستند، اما زنجیره کردن آن‌ها به یک گردش کار امن، منسجم و مقاوم همیشه نیازمند بیش از فقط چسباندن تماس‌ها به هم و خوب دانستن آن بوده است. چه در حال هماهنگی میکروسرویس‌ها باشید یا اتصال APIهای شخص ثالث به محصولات شبکه‌ای، زنجیره کردن APIها فرآیندی پیچیده است. امروز، ما به سه رویکرد رایج برای اتصال چندین API به یکدیگر نگاه خواهیم کرد. به صورت عملی به آنچه این‌ها به نظر می‌رسند خواهیم پرداخت و خواهیم دید که دنیای هوش مصنوعی در مورد این فرآیند چه می‌گوید.

۱. جریان‌های API سریال‌شده (Serialized API Flows)

ساده‌ترین — هرچند کم‌انعطاف‌ترین — رویکرد، سریال کردن جریان‌های API از یک تماس به تماس بعدی است. در این مدل، خروجی یک API را می‌گیرید و مستقیماً آن را به دیگری تغذیه می‌کنید، و آن را کمی تغییر می‌دهید تا با فرمت ورودی مورد انتظار مطابقت داشته باشد. یک سریال‌سازی ساده را با استفاده از یک API ثبت‌نام و یک API غنی‌سازی برای ساخت یک پروفایل کاربری کامل‌تر در نظر بگیرید. وقتی کاربری برای سرویس ما ثبت‌نام می‌کند، می‌خواهیم پروفایل او را با استفاده از منابع داده‌ای خود غنی‌سازی کنیم و سپس داده را به عنوان یک پروفایل کاربری ذخیره کنیم. این شامل سه API است که به ترتیب کار می‌کنند. ابتدا، درخواست ثبت‌نام اولیه را در نظر بگیرید:

makefile
signup_response = requests.post("https://api.example.com/signup", json={
    "name": "Jane Doe",
    "email": "jane@example.com",
    "password": "secure123"
})
signup_data = signup_response.json()
email = signup_data["email"]

از اینجا، می‌توانیم ایمیل را بگیریم و آن را به یک نقطه پایانی غنی‌سازی جداگانه تغذیه کنیم:

makefile
enrich_response = requests.get(f"https://api.example.com/enrichment?email={email}", headers={
    "Authorization": "Bearer bearerkey"
})
enrich_data = enrich_response.json()

با گذراندن ایمیل برگشتی از درخواست اول به API /enrichment، ما خروجی یک تماس را مستقیماً به تماس بعدی زنجیره می‌کنیم. حالا می‌توانیم نتایج فرآیند غنی‌سازی را بگیریم و آن‌ها را به نقطه پایانی دیگری برای به‌روزرسانی رکورد کاربری داخلی فشار دهیم:

csharp
requests.post("https://api.example.com/users", json={
    "user_id": signup_data["id"],
    "company": enrich_data.get("company"),
    "title": enrich_data.get("title"),
    "linkedin": enrich_data.get("linkedin")
})
`

این فرآیند ساده برای پیاده‌سازی است. اما محدود نیز هست — شما فقط داده را از مرحله به مرحله سریال می‌کنید، بدون مدیریت داخلی برای اقدامات پیچیده‌تر. برای گردش کارهای سریع خوب است، اما اگر چندین API وابسته را ارکستراسیون می‌کنید یا حالت طولانی‌مدت را مدیریت می‌کنید، به چیزی قوی‌تر نیاز خواهید داشت.

۲. توالی‌های API مبتنی بر مشخصات (Specification-Driven API Sequences)

گام بعدی، نگاه به پیاده‌سازی‌های مبتنی بر مشخصات، مانند مشخصات Arazzo است. Arazzo مشخصه‌ای است که تحت ابتکار OpenAPI به عنوان بخشی از تلاش بنیاد لینوکس برای استانداردسازی طراحی و پیاده‌سازی مشخصات توسعه یافته است. این رویکرد یک مشخصات رسمی برای سریال کردن گردش کارهای ارائه می‌دهد، که توالی تماس‌ها و عناصر مشترک در میان آن تماس‌ها را توصیف می‌کند. این اجازه می‌دهد تا جریان پیچیده‌تری ایجاد کنیم که از طریق اعلام، قابلیت پیش‌بینی، قابلیت همکاری بهتر و قابلیت حمل تمیزتر گردش کارهای مبتنی بر Arazzo را داشته باشد. به مثال قبلی خود نگاه کنیم، جایی که می‌خواهیم اجازه دهیم کاربر ثبت‌نام کند و سپس این پروفایل را غنی‌سازی کنیم. به طور قابل توجه، یک مرحله تأیید در این جریان شامل خواهیم کرد تا اطمینان حاصل کنیم داده‌هایی که جمع‌آوری کرده‌ایم دقیق است.

yaml
arazzo: 1.0.1
info:
  title: User Onboarding Workflow
  version: 1.0.0
  description: >
    A workflow that handles user signup, enriches the user's profile,
    and verifies the enriched data.

sourceDescriptions:
  - name: userAPI
    url: https://api.example.com/openapi.yaml
    type: openapi

workflows:
  - workflowId: userOnboarding
    summary: Sign up a user, enrich their profile, and verify the data.
    inputs:
      type: object
      properties:
        name:
          type: string
        email:
          type: string
        password:
          type: string
      required:
        - name
        - email
        - password
    steps:
      - stepId: signUpUser
        operationId: createUser
        parameters:
          - name: name
            in: body
            value: $inputs.name
          - name: email
            in: body
            value: $inputs.email
          - name: password
            in: body
            value: $inputs.password
        outputs:
          userId: $response.body.id
          email: $response.body.email

      - stepId: enrichProfile
        operationId: enrichUser
        parameters:
          - name: email
            in: query
            value: $steps.signUpUser.outputs.email
        outputs:
          company: $response.body.company
          title: $response.body.title
          linkedin: $response.body.linkedin

      - stepId: verifyData
        operationId: verifyUserData
        parameters:
          - name: userId
            in: body
            value: $steps.signUpUser.outputs.userId
          - name: company
            in: body
            value: $steps.enrichProfile.outputs.company
          - name: title
            in: body
            value: $steps.enrichProfile.outputs.title

بیایید این را قطعه به قطعه تجزیه کنیم. ابتدا، فیلدهای ثابت مورد نیاز در Arazzo را داریم:

yaml
arazzo: 1.0.1
info:
  title: User Onboarding Workflow
  version: 1.0.0
  description: >
    A workflow that handles user signup, enriches the user's profile,
    and verifies the enriched data.

sourceDescriptions:
  - name: userAPI
    url: https://api.example.com/openapi.yaml
    type: openapi

workflows:

رشته arazzo شماره نسخه‌ای را که برای تفسیر بقیه سند استفاده می‌شود، اعلام می‌کند. از اینجا، شیء info متادیتا را برای گردش کار تنظیم می‌کند، عنوان، نسخه و توضیحات را اعلام می‌کند. بعدی، باید sourceDescriptions را تعریف کنیم، که اعلام می‌کند توضیحات به چه چیزی در بدنه بزرگ‌تر OpenAPI اعمال می‌شود. در نهایت، شروع به تعریف گردش کارهای واقعی می‌کنیم. ابتدا، گردش کار برای ثبت‌نام کاربر:

yaml
workflows:
  - workflowId: userOnboarding
    summary: Sign up a user, enrich their profile, and verify the data.
    inputs:
      type: object
      properties:
        name:
          type: string
        email:
          type: string
        password:
          type: string
      required:
        - name
        - email
        - password
    steps:
      - stepId: signUpUser
        operationId: createUser
        parameters:
          - name: name
            in: body
            value: $inputs.name
          - name: email
            in: body
            value: $inputs.email
          - name: password
            in: body
            value: $inputs.password
        outputs:
          userId: $response.body.id
          email: $response.body.email

این اجازه می‌دهد تا مقادیر ورودی پایه برای جریان ثبت‌نام کاربر را ثبت کنیم. بعدی، باید یک گردش کار ادامه‌دار در اطراف فرآیند غنی‌سازی تنظیم کنیم:

yaml
- stepId: enrichProfile
        operationId: enrichUser
        parameters:
          - name: email
            in: query
            value: $steps.signUpUser.outputs.email
        outputs:
          company: $response.body.company
          title: $response.body.title
          linkedin: $response.body.linkedin

این از ایمیل ارائه‌شده در کوئری به عنوان ورودی استفاده خواهد کرد، آن را با خروجی‌های پایگاه داده غنی‌سازی جفت می‌کند. این خروجی‌ها سپس در درخواست کلی بسته‌بندی خواهند شد و در مرحله تأیید استفاده می‌شوند:

yaml
- stepId: verifyData
        operationId: verifyUserData
        parameters:
          - name: userId
            in: body
            value: $steps.signUpUser.outputs.userId
          - name: company
            in: body
            value: $steps.enrichProfile.outputs.company
          - name: title
            in: body
            value: $steps.enrichProfile.outputs.title

در اینجا، داده‌های ارائه‌شده تا کنون برای جستجوی داده‌های معتبر و تأییدشده استفاده خواهد شد، اطمینان حاصل می‌کند که داده‌های متصل به کاربر واقعاً به درستی نسبت داده شده است.

۳. اتصالات API کنترل شده توسط هوش مصنوعی (AI-Orchestrated API Connections)

یک تکامل کاملاً مدرن این فرآیند، استفاده از راه‌حل‌های عامل‌محور مبتنی بر هوش مصنوعی برای توالی‌های API است. عامل‌های هوش مصنوعی معکوس یک راه‌حل مبتنی بر مشخصات را نشان می‌دهند. به جای پیش‌تعریف ساختار جریان، شما یک موتور استدلال ایجاد می‌کنید که تماس API بعدی را بر اساس زمینه فعلی و قصد درخواست تعیین می‌کند. این به ویژه در موقعیت‌هایی مفید است که hypermedia، آن عنصر RESTful که انواع رسانه پیچیده را از طریق لینک‌های قابل پیمایش متصل می‌کند، لایه اضافی پیچیدگی اضافه می‌کند که از طریق مسیریابی نقطه پایانی IF/THEN به سادگی حل نمی‌شود. این می‌تواند فرمت‌های زیادی بگیرد، اما اینجا یک مثال جریان ساده است:

python
import requests
import openai
import json

openai.api_key = "sk-..."  # Your OpenAI API key

در اینجا کلید OpenAI را برای تسهیل درخواست‌هایمان در سراسر این فرآیند تنظیم می‌کنیم. برای شروع، باید جایی برای وقوع ثبت‌نام کاربر داشته باشیم. فرض کنیم این در یک تماس API خارجی اتفاق می‌افتد، و ما یک شیء JSON مانند این به عنوان پاسخ به سیستم دریافت می‌کنیم:

makefile
signup_response = requests.post("https://api.example.com/signup", json={
    "name": "Jane Doe",
    "email": "jane@example.com",
    "password": "secure123"
}).json()

با این، می‌توانیم شیء JSON را به GTP با استفاده از کد زیر پاس دهیم:

swift
messages = [
    {
        "role": "system",
        "content": (
            "You are an API orchestration engine. Based on API responses you receive,"
            "decide what API should be called next, using structured JSON. "
            "Do not speculate - respond only using the data provided. Format:\n\n"
            "{\n"
            "  \"action\": \"next_api_to_call\",\n"
            "  \"payload\": { ...fields... }\n"
            "}\n\n"
            "If no further steps are needed, respond with { \"action\": \"complete\" }"
        )
    },
    {
        "role": "user",
        "content": f "Here is the response from the signup API:\n{json.dumps(signup_response)}"
    }
]
`

این اجازه می‌دهد تا نقش و محتوای درخواست را تنظیم کنیم، به OpenAI اطلاع دهیم که آن‌ها یک موتور ارکستراسیون API هستند که اقدامات را بر اساس جریان API مورد نظر تعیین خواهند کرد. بعدی، GPT تصمیمی خواهد گرفت که با استفاده از این کد به ما بازگردانده می‌شود:

lua
decision_1 = openai.ChatCompletion.create(
    model="gpt-4",
    messages=messages,
    temperature=0
)['choices'][0]['message']['content']

print("GPT Decision 1:\n", decision_1)

با پاسخ در دست، می‌توانیم این خروجی را تجزیه کنیم و اقدام کنیم، یا به سیستم داخلی هشدار دهیم که خطایی وجود دارد که نیاز به اقدام دستی دارد:

python
try:
    decision_data = json.loads(decision_1)
except json.JSONDecodeError:
    print("Error - GPT response was not valid JSON. Cannot proceed.")
    exit(1)

action = decision_data.get("action")
payload = decision_data.get("payload", {})

if action == "call_enrichment_api":
    email = payload.get("email")
    enrich_response = requests.get(
        f"https://api.example.com/enrichment?email={email}",
        headers={"Authorization": "Bearer bearerkey"}
    )
    print("Enrichment Response:\n", enrich_response.json())

elif action == "call_verification_api":
    verify_response = requests.post(
        "https://api.example.com/verify",
        json=payload
    )
    print("Verification Response:\n", verify_response.json())

elif action == "complete":
    print("Workflow complete.")

else:
    print(f"Error - Unknown action '{action}'. Manual intervention required.")

این یک پیاده‌سازی نسبتاً ساده است، اما واگذاری این منطق به GPT کارهای زیادی برای فعال کردن تعاملات پیچیده با سربار حداقل انجام می‌دهد. جایی که این کمی پیچیده‌تر می‌شود، در تعاملات چندمرحله‌ای است — برای مثال، اگر نیاز داشته باشیم OpenAI تصمیمی بر اساس تصمیم اولیه و همچنین تصمیماتی که می‌تواند بر اساس داده‌های سیستم تأیید ارائه دهد، بگیرد. در چنین سناریویی، شروع به نگاه به آرایه‌های ذخیره‌شده، اشیاء پایگاه داده و غیره می‌کنیم، که فراتر از دامنه این مقاله است.

مستندات هدایت‌شده توسط ارائه‌دهنده API

گاهی اوقات، ارائه‌دهنده API به صراحت اعلام می‌کند چگونه یک توالی از تماس‌های API را به هم متصل کند. برای مثال، یک ارائه‌دهنده API ممکن است یک جریان احراز هویت چندمرحله‌ای را در مستندات خود ترسیم کند. با این حال، این در عمل نادر است. حتی در مواردی مانند Stripe، که روش خاصی برای اتصال چندین نمونه API به هم توصیه می‌کند، آن‌ها بسیار کلی‌تر قابل اعمال هستند، هنوز نیاز به خاص بودن در پیاده‌سازی برای موارد استفاده پیچیده‌تر دارند.

صنعت به کجا می‌رود

این بحث هنوز بسیار فعال است. فضای API مدت‌هاست با چگونگی اتصال APIها دست و پنجه نرم می‌کند، و پیشرفت‌های نوین در فضای هوش مصنوعی گفتگوهای اخیر را زیر و رو کرده است. عامل‌های interconnected، لایه‌های middleware که مدل‌ها را به مدل‌ها برای استدلال چندوجهی مبتنی بر تعارض متصل می‌کنند، و حتی زنجیره‌های چندعامل برای تجزیه پیچیده بسیار رایج‌تر از یک یا دو سال پیش شده‌اند، عمدتاً به دلیل پیشرفت‌هایی مانند پروتکل زمینه مدل (MCP). اگر سؤال این باشد که «چگونه چندین API را به هم زنجیره کنیم»، پاسخ این است که هیچ راه «درست»ی وجود ندارد، مگر فرآیند تعیین‌شده یا توصیه‌شده از سوی خود ارائه‌دهنده API. واقعیت این است که گزینه‌های توالی API شما عمدتاً توسط سیستم‌های زیربنایی آن‌ها تعریف خواهند شد. برای مثال، یک برنامه بومی LLM به طور طبیعی به سمت اتصال مبتنی بر هوش مصنوعی گرایش خواهد داشت زیرا فناوری از قبل وجود دارد و آماده استفاده است. برای APIهای سنتی بدون ادغام LLM که فقط می‌خواهند داده را از یک API به دیگری لوله‌کشی کنند، یک راه‌حل هوش مصنوعی بیش از حد خواهد بود. آنچه این بحث را ابری می‌کند این واقعیت است که تمام این توصیه‌ها ممکن است یک سال دیگر منسوخ شود. ما در زمانی از تکامل سریع هستیم، و با تکامل سیستم‌های LLM و راه‌حل‌های جدید مانند MCP که قول حاکمیت بر interconnections را می‌دهند، دنیای اتصال API بزرگ‌ترین لرزشی را که از زمان غلبه طراحی RESTful بر SOAP به عنوان پارادایم انتخابی در دهه‌های ۲۰۰۰ و ۲۰۱۰ دیده شده، تجربه می‌کند. توصیه، پس، ساده است: بهترین راه‌حل خود را برای حالا انتخاب کنید، اما این را ثابت یا نهایی در نظر نگیرید. احتمالاً روش‌شناسی خود را در مدت کوتاهی تغییر خواهید داد.

بازسازی کد (Code Refactoring) چیست؟
نقش دروازه‌های هوش مصنوعی (AI Gateways) و ارتباط آن‌ها با APIها در چیست؟

دیدگاهتان را بنویسید

سبد خرید
علاقه‌مندی‌ها
مشاهدات اخیر
دسته بندی ها