برنامه نویسی

با LangGraph، CopilotKit، Tavily و Next.js یک کلون از Perplexity بسازید.

برنامه های کاربردی مبتنی بر هوش مصنوعی فراتر از عوامل مستقلی هستند که وظایف را انجام می دهند. یک رویکرد جدید شامل Human-in-the-Loop به کاربران این امکان را می دهد که بازخورد ارائه دهند، نتایج را بررسی کنند و در مورد مراحل بعدی هوش مصنوعی تصمیم بگیرند. این عوامل زمان اجرا به عنوان CoAgents شناخته می شوند.

TL; DR

در این آموزش، نحوه ساخت یک کلون Perplexity با استفاده از LangGraph، CopilotKit و Tavily را خواهید آموخت.

زمان شروع ساخت و ساز

خلبان عامل چیست؟

CopilotKit چگونه عوامل LangGraph را به برنامه شما می آورد.

CoAgents رویکرد CopilotKit برای ایجاد تجربیات نمایندگی است!

به‌طور خلاصه، درخواست‌های کاربر را با انجام چندین پرس‌و‌جوی جستجو انجام می‌دهد و جستجو را با وضعیت و نتایج در زمان واقعی برای مشتری ارسال می‌کند.

CopilotKit را بررسی کنید ⭐️


پیش نیازها

برای درک کامل این آموزش، باید درک اولیه ای از React یا Next.js داشته باشید.

ما همچنین از موارد زیر استفاده خواهیم کرد:

  • Python – یک زبان برنامه نویسی محبوب برای ساخت عوامل هوش مصنوعی با LangGraph. مطمئن شوید که روی کامپیوتر شما نصب شده است.

  • LangGraph – چارچوبی برای ایجاد و استقرار عوامل هوش مصنوعی. همچنین به تعریف جریان های کنترلی و اقداماتی که باید توسط عامل انجام شود کمک می کند.

  • کلید OpenAI API – به ما امکان می دهد تا با استفاده از مدل های GPT وظایف مختلفی را انجام دهیم. برای این آموزش، مطمئن شوید که به مدل GPT-4 دسترسی دارید.

  • Tavily AI – یک موتور جستجو که عوامل هوش مصنوعی را قادر می سازد تحقیقات انجام دهند و به دانش زمان واقعی در برنامه دسترسی پیدا کنند.

  • CopilotKit – یک چارچوب منبع باز کمکی برای ساخت چت ربات های سفارشی هوش مصنوعی، عوامل هوش مصنوعی درون برنامه ای و مناطق متنی.

  • Shad Cn UI – مجموعه ای از اجزای رابط کاربری قابل استفاده مجدد را در برنامه ارائه می دهد.


نحوه ایجاد عوامل هوش مصنوعی با LangGraph و CopilotKit

در این بخش، نحوه ایجاد یک عامل هوش مصنوعی با استفاده از LangGraph و CopilotKit را یاد خواهید گرفت.

ابتدا مخزن استارتر CopilotKit CoAgents را کلون کنید. این ui دایرکتوری شامل frontend برای برنامه Next.js و agent دایرکتوری CoAgent را برای برنامه نگه می دارد.

در داخل agent دایرکتوری، وابستگی های پروژه را با استفاده از Poetry نصب کنید.

cd agent
poetry install
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ایجاد یک .env در پوشه agent فایل کنید و کلیدهای OpenAI و Tavily AI API خود را در فایل کپی کنید:

OPENAI_API_KEY=
TAVILY_API_KEY=
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کلید OpenAI API را دریافت کنید

قطعه کد زیر را در قسمت کپی کنید agent.py فایل:

"""
This is the main entry point for the AI.
It defines the workflow graph and the entry point for the agent.
"""
# pylint: disable=line-too-long, unused-import
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver

from ai_researcher.state import AgentState
from ai_researcher.steps import steps_node
from ai_researcher.search import search_node
from ai_researcher.summarize import summarize_node
from ai_researcher.extract import extract_node

def route(state):
    """Route to research nodes."""
    if not state.get("steps", None):
        return END

    current_step = next((step for step in state["steps"] if step["status"] == "pending"), None)

    if not current_step:
        return "summarize_node"

    if current_step["type"] == "search":
        return "search_node"

    raise ValueError(f"Unknown step type: {current_step['type']}")

# Define a new graph
workflow = StateGraph(AgentState)
workflow.add_node("steps_node", steps_node)
workflow.add_node("search_node", search_node)
workflow.add_node("summarize_node", summarize_node)
workflow.add_node("extract_node", extract_node)
# Chatbot
workflow.set_entry_point("steps_node")

workflow.add_conditional_edges(
    "steps_node", 
    route,
    ["summarize_node", "search_node", END]
)

workflow.add_edge("search_node", "extract_node")

workflow.add_conditional_edges(
    "extract_node",
    route,
    ["summarize_node", "search_node"]
)

workflow.add_edge("summarize_node", END)

memory = MemorySaver()
graph = workflow.compile(checkpointer=memory)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه کد بالا گردش کار عامل LangGraph را تعریف می کند. از آن شروع می شود steps_node، نتایج را جستجو می کند، آنها را خلاصه می کند و نکات کلیدی را استخراج می کند.

گردش کار نماینده

بعد ایجاد یک demo.py فایل با قطعه کد زیر:


"""Demo"""

import os
from dotenv import load_dotenv
load_dotenv()

from fastapi import FastAPI
import uvicorn
from copilotkit.integrations.fastapi import add_fastapi_endpoint
from copilotkit import CopilotKitSDK, LangGraphAgent
from ai_researcher.agent import graph

app = FastAPI()
sdk = CopilotKitSDK(
    agents=[
        LangGraphAgent(
            name="ai_researcher",
            description="Search agent.",
            graph=graph,
        )
    ],
)

add_fastapi_endpoint(app, sdk, "/copilotkit")

# add new route for health check
@app.get("/health")
def health():
    """Health check."""
    return {"status": "ok"}

def main():
    """Run the uvicorn server."""
    port = int(os.getenv("PORT", "8000"))
    uvicorn.run("ai_researcher.demo:app", host="0.0.0.0", port=port, reload=True)

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد بالا یک نقطه پایانی FastAPI ایجاد می کند که عامل LangGraph را میزبانی می کند و آن را به CopilotKit SDK متصل می کند.

می توانید کد باقیمانده برای ایجاد CoAgent را از مخزن GitHub کپی کنید. در بخش‌های بعدی، نحوه ساخت رابط کاربری برای کلون Perplexity و رسیدگی به درخواست‌های جستجو با استفاده از CopilotKit را خواهید آموخت.


ساخت رابط برنامه با Next.js

در این بخش، شما را از طریق فرآیند ساخت رابط کاربری برای برنامه راهنمایی خواهم کرد.

ابتدا با اجرای قطعه کد زیر یک پروژه Next.js Typescript ایجاد کنید:

# 👉🏻 Navigate into the ui folder
npx create-next-app ./
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نصب Next.js

با اجرای قطعه کد زیر، کتابخانه ShadCn UI را در پروژه جدید ایجاد شده نصب کنید:

npx shadcn@latest init
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بعد، a ایجاد کنید components پوشه در ریشه پروژه Next.js، سپس آن را کپی کنید ui پوشه از این مخزن GitHub به آن پوشه. Shadcn به شما این امکان را می دهد که به راحتی با نصب اجزای مختلف از طریق خط فرمان به برنامه خود اضافه کنید.

علاوه بر مؤلفه‌های Shadcn، باید چند مؤلفه ایجاد کنید که نمایانگر بخش‌های مختلف رابط برنامه باشد. قطعه کد زیر را در داخل اجرا کنید components پوشه ای برای افزودن این مؤلفه ها به پروژه Next.js:

touch ResearchWrapper.tsx ResultsView.tsx HomeView.tsx
touch AnswerMarkdown.tsx Progress.tsx SkeletonLoader.tsx
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه کد زیر را در قسمت کپی کنید app/page.tsx فایل:

"use client";

import { ResearchWrapper } from "@/components/ResearchWrapper";
import { ModelSelectorProvider, useModelSelectorContext } from "@/lib/model-selector-provider";
import { ResearchProvider } from "@/lib/research-provider";
import { CopilotKit } from "@copilotkit/react-core";
import "@copilotkit/react-ui/styles.css";

export default function ModelSelectorWrapper() {

  return (
      <CopilotKit runtimeUrl={useLgc ? "/api/copilotkit-lgc" : "/api/copilotkit"} agent="ai_researcher">
        <ResearchProvider>
          <ResearchWrapper />
        </ResearchProvider>
      </CopilotKit>
  );
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در قطعه کد بالا، ResearchProvider یک ارائه‌دهنده زمینه سفارشی React است که پرس و جو و نتایج جستجوی کاربر را به اشتراک می‌گذارد و آنها را برای همه اجزای برنامه قابل دسترسی می‌کند. این ResearchWrapper جزء شامل عناصر اصلی برنامه است و رابط کاربری را مدیریت می کند.

ایجاد یک lib پوشه حاوی الف research-provider.tsx فایل را در ریشه پروژه Next.js قرار دهید و کد زیر را در فایل کپی کنید:

import { createContext, useContext, useState, ReactNode, useEffect } from "react";

type ResearchContextType = {
  researchQuery: string;
  setResearchQuery: (query: string) => void;
  researchInput: string;
  setResearchInput: (input: string) => void;
  isLoading: boolean;
  setIsLoading: (loading: boolean) => void;
  researchResult: ResearchResult | null;
  setResearchResult: (result: ResearchResult) => void;
};

type ResearchResult = {
  answer: string;
  sources: string[];
}

const ResearchContext = createContext<ResearchContextType | undefined>(undefined);

export const ResearchProvider = ({ children }: { children: ReactNode }) => {
  const [researchQuery, setResearchQuery] = useState<string>("");
  const [researchInput, setResearchInput] = useState<string>("");
  const [researchResult, setResearchResult] = useState<ResearchResult | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(false);

  useEffect(() => {
    if (!researchQuery) {
      setResearchResult(null);
      setResearchInput("");
    }
  }, [researchQuery, researchResult]);

  return (
    <ResearchContext.Provider
      value={{
        researchQuery,
        setResearchQuery,
        researchInput,
        setResearchInput,
        isLoading,
        setIsLoading,
        researchResult,
        setResearchResult,
      }}
    >
      {children}
    </ResearchContext.Provider>
  );
};

export const useResearchContext = () => {
  const context = useContext(ResearchContext);
  if (context === undefined) {
    throw new Error("useResearchContext must be used within a ResearchProvider");
  }
  return context;
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ایالت ها اعلام شده و در آن ذخیره می شوند ResearchContext برای اطمینان از مدیریت صحیح آنها در چندین مؤلفه در برنامه.

ایجاد یک ResearchWrapper جزء مطابق شکل زیر:

import { HomeView } from "./HomeView";
import { ResultsView } from "./ResultsView";
import { AnimatePresence } from "framer-motion";
import { useResearchContext } from "@/lib/research-provider";

export function ResearchWrapper() {
  const { researchQuery, setResearchInput } = useResearchContext();

  return (
    <>
      <div className="flex flex-col items-center justify-center relative z-10">
        <div className="flex-1">
          {researchQuery ? (
            <AnimatePresence
              key="results"
              onExitComplete={() => {
                setResearchInput("");
              }}
              mode="wait"
            >
              <ResultsView key="results" />
            </AnimatePresence>
          ) : (
            <AnimatePresence key="home" mode="wait">
              <HomeView key="home" />
            </AnimatePresence>
          )}
        </div>
        <footer className="text-xs p-2">
          <a
            href="https://copilotkit.ai"
            target="_blank"
            rel="noopener noreferrer"
            className="text-slate-600 font-medium hover:underline"
          >
            Powered by CopilotKit 🪁
          </a>
        </footer>
      </div>
    </>
  );
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این ResearchWrapper جزء را ارائه می دهد HomeView جزء به عنوان نمای پیش فرض و نمایش داده می شود ResultView هنگامی که یک عبارت جستجو ارائه می شود. این useResearchContext قلاب ما را قادر می سازد تا به researchQuery بر اساس آن نمای را بیان و به روز کنید.

در نهایت، ایجاد کنید HomeView جزء برای رندر رابط صفحه اصلی برنامه.

"use client";

import { useEffect, useState } from "react";
import { Textarea } from "./ui/textarea";
import { cn } from "@/lib/utils";
import { Button } from "./ui/button";
import { CornerDownLeftIcon } from "lucide-react";
import { useResearchContext } from "@/lib/research-provider";
import { motion } from "framer-motion";
import { useCoAgent } from "@copilotkit/react-core";
import { TextMessage, MessageRole } from "@copilotkit/runtime-client-gql";
import type { AgentState } from "../lib/types";
import { useModelSelectorContext } from "@/lib/model-selector-provider";

const MAX_INPUT_LENGTH = 250;

export function HomeView() {
  const { setResearchQuery, researchInput, setResearchInput } =
    useResearchContext();
  const { model } = useModelSelectorContext();
  const [isInputFocused, setIsInputFocused] = useState(false);
  const {
    run: runResearchAgent,
  } = useCoAgent<AgentState>({
    name: "ai_researcher",
    initialState: {
      model,
    },
  });

  const handleResearch = (query: string) => {
    setResearchQuery(query);
    runResearchAgent(() => {
      return new TextMessage({
        role: MessageRole.User,
        content: query,
      });
    });
  };

  const suggestions = [
    { label: "Electric cars sold in 2024 vs 2023", icon: "🚙" },
    { label: "Top 10 richest people in the world", icon: "💰" },
    { label: "Population of the World", icon: "🌍 " },
    { label: "Weather in Seattle VS New York", icon: "⛅️" },
  ];

  return (
    <motion.div
      initial={{ opacity: 0, y: -50 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0 }}
      transition={{ duration: 0.4 }}
      className="h-screen w-full flex flex-col gap-y-2 justify-center items-center p-4 lg:p-0"
    >
      <h1 className="text-4xl font-extralight mb-6">
        What would you like to know?
      </h1>

      <div
        className={cn(
          "w-full bg-slate-100/50 border shadow-sm rounded-md transition-all",
          {
            "ring-1 ring-slate-300": isInputFocused,
          }
        )}
      >
        <Textarea
          placeholder="Ask anything..."
          className="bg-transparent p-4 resize-none focus-visible:ring-0 focus-visible:ring-offset-0 border-0 w-full"
          onFocus={() => setIsInputFocused(true)}
          onBlur={() => setIsInputFocused(false)}
          value={researchInput}
          onChange={(e) => setResearchInput(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter" && !e.shiftKey) {
              e.preventDefault();
              handleResearch(researchInput);
            }
          }}
          maxLength={MAX_INPUT_LENGTH}
        />
        <div className="text-xs p-4 flex items-center justify-between">
          <div
            className={cn("transition-all duration-300 mt-4 text-slate-500", {
              "opacity-0": !researchInput,
              "opacity-100": researchInput,
            })}
          >
            {researchInput.length} / {MAX_INPUT_LENGTH}
          </div>
          <Button
            size="sm"
            className={cn("rounded-full transition-all duration-300", {
              "opacity-0 pointer-events-none": !researchInput,
              "opacity-100": researchInput,
            })}
            onClick={() => handleResearch(researchInput)}
          >
            Research
            <CornerDownLeftIcon className="w-4 h-4 ml-2" />
          </Button>
        </div>
      </div>
      <div className="grid grid-cols-2 w-full gap-2 text-sm">
        {suggestions.map((suggestion) => (
          <div
            key={suggestion.label}
            onClick={() => handleResearch(suggestion.label)}
            className="p-2 bg-slate-100/50 rounded-md border col-span-2 lg:col-span-1 flex cursor-pointer items-center space-x-2 hover:bg-slate-100 transition-all duration-300"
          >
            <span className="text-base">{suggestion.icon}</span>
            <span className="flex-1">{suggestion.label}</span>
          </div>
        ))}
      </div>
    </motion.div>
  );
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

صفحه اصلی برنامه


چگونه CoAgent خود را به یک برنامه Next.js متصل کنیم

در این بخش، یاد خواهید گرفت که چگونه CopilotKit CoAgent را به برنامه Next.js خود متصل کنید تا کاربران بتوانند عملیات جستجو را در برنامه انجام دهند.

بسته های CopilotKit زیر و OpenAI Node.js SDK را نصب کنید. بسته های CopilotKit به عامل مشترک اجازه می دهد تا با مقادیر React حالت تعامل داشته باشد و در داخل برنامه تصمیم گیری کند.

npm install @copilotkit/react-core @copilotkit/react-ui @copilotkit/runtime @copilotkit/runtime-client-gql openai
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ایجاد کنید api پوشه در Next.js app پوشه در داخل api پوشه، ایجاد یک copilotkit دایرکتوری حاوی الف route.ts فایل این یک نقطه پایانی API ایجاد می کند (/api/copilotkit) که برنامه frontend را به CopilotKit CoAgent متصل می کند.

cd app
mkdir api && cd api
mkdir copilotkit && cd copilotkit
touch route.ts
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه کد زیر را در قسمت کپی کنید api/copilotkit/route.ts فایل:

import { NextRequest } from "next/server";
import {
  CopilotRuntime,
  OpenAIAdapter,
  copilotRuntimeNextJSAppRouterEndpoint,
} from "@copilotkit/runtime";
import OpenAI from "openai";

//👇🏻 initializes OpenAI as the adapter
const openai = new OpenAI();
const serviceAdapter = new OpenAIAdapter({ openai } as any);

//👇🏻 connects the CopilotKit runtime to the CoAgent
const runtime = new CopilotRuntime({
  remoteEndpoints: [
    {
      url: process.env.REMOTE_ACTION_URL || "http://localhost:8000/copilotkit",
    },
  ],
});

export const POST = async (req: NextRequest) => {
  const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
    runtime,
    serviceAdapter,
    endpoint: "/api/copilotkit",
  });

  return handleRequest(req);
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه کد بالا زمان اجرا CopilotKit را در /api/copilotkit نقطه پایانی API، به CopilotKit اجازه می دهد تا درخواست های کاربر را از طریق عامل مشترک هوش مصنوعی پردازش کند.

در نهایت، به روز رسانی کنید app/page.tsx با بسته بندی کل برنامه با مولفه CopilotKit که زمینه کمکی را برای همه اجزای برنامه فراهم می کند.

"use client";

import { ModelSelector } from "@/components/ModelSelector";
import { ResearchWrapper } from "@/components/ResearchWrapper";
import { ModelSelectorProvider, useModelSelectorContext } from "@/lib/model-selector-provider";
import { ResearchProvider } from "@/lib/research-provider";
import { CopilotKit } from "@copilotkit/react-core";
import "@copilotkit/react-ui/styles.css";

export default function ModelSelectorWrapper() {
  return (
      <main className="flex flex-col items-center justify-between">
        <ModelSelectorProvider>
            <Home/>
          <ModelSelector />
        </ModelSelectorProvider>
      </main>
  );
}

function Home() {
  const { useLgc } = useModelSelectorContext();

  return (
      <CopilotKit runtimeUrl={useLgc ? "/api/copilotkit-lgc" : "/api/copilotkit"} agent="ai_researcher">
        <ResearchProvider>
          <ResearchWrapper />
        </ResearchProvider>
      </CopilotKit>
  );
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مؤلفه CopilotKit کل برنامه را می پیچد و دو پروپوزال را می پذیرد – runtimeUrl و agent. این runtimeUrl مسیر API باطنی است که میزبان عامل هوش مصنوعی و agent نام عاملی است که عمل را انجام می دهد.

پذیرش درخواست ها و پاسخ های جریانی به فرانت اند

برای فعال کردن CopilotKit برای دسترسی و پردازش ورودی های کاربر، آن را فراهم می کند useCoAgent hook، که امکان دسترسی به وضعیت عامل را از هر نقطه در برنامه فراهم می کند.

به عنوان مثال، قطعه کد زیر نحوه استفاده از آن را نشان می دهد useCoAgent قلاب این state متغیر اجازه دسترسی به وضعیت فعلی عامل را می دهد، setState برای تغییر وضعیت استفاده می شود و از run تابع دستورات را با استفاده از عامل اجرا می کند. این start و stop توابع اجرای عامل را آغاز و متوقف می کنند.

const { state, setState, run, start, stop } = useCoAgent({
    name: "search_agent",
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

را به روز کنید HomeView مؤلفه ای برای اجرای عامل در هنگام ارائه درخواست جستجو.

//👇🏻 import useCoAgent hook from CopilotKit
import { useCoAgent } from "@copilotkit/react-core";

const { run: runResearchAgent } = useCoAgent({
    name: "search_agent",
});

const handleResearch = (query: string) => {
    setResearchQuery(query);
    runResearchAgent(query); //👉🏻 starts the agent execution
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در مرحله بعد، می‌توانید نتایج جستجو را به صفحه پخش کنید ResultsView با دسترسی به متغیر state در داخل useCoAgent قلاب قطعه کد زیر را در قسمت کپی کنید ResultsView جزء

"use client";

import { useResearchContext } from "@/lib/research-provider";
import { motion } from "framer-motion";
import { BookOpenIcon, LoaderCircleIcon, SparkleIcon } from "lucide-react";
import { SkeletonLoader } from "./SkeletonLoader";
import { useCoAgent } from "@copilotkit/react-core";
import { Progress } from "./Progress";
import { AnswerMarkdown } from "./AnswerMarkdown";

export function ResultsView() {
    const { researchQuery } = useResearchContext();
    //👇🏻 agent state
    const { state: agentState } = useCoAgent({
        name: "search_agent",
    });

    console.log("AGENT_STATE", agentState);

    //👇🏻 keeps track of the current agent processing state
    const steps =
        agentState?.steps?.map((step: any) => {
            return {
                description: step.description || "",
                status: step.status || "pending",
                updates: step.updates || [],
            };
        }) || [];

    const isLoading = !agentState?.answer?.markdown;

    return (
        <motion.div
            initial={{ opacity: 0, y: -50 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -50 }}
            transition={{ duration: 0.5, ease: "easeOut" }}
        >
            <div className='max-w-[1000px] p-8 lg:p-4 flex flex-col gap-y-8 mt-4 lg:mt-6 text-sm lg:text-base'>
                <div className='space-y-4'>
                    <h1 className='text-3xl lg:text-4xl font-extralight'>
                        {researchQuery}
                    </h1>
                </div>

                <Progress steps={steps} />

                <div className='grid grid-cols-12 gap-8'>
                    <div className='col-span-12 lg:col-span-8 flex flex-col'>
                        <h2 className='flex items-center gap-x-2'>
                            {isLoading ? (
                                <LoaderCircleIcon className='animate-spin w-4 h-4 text-slate-500' />
                            ) : (
                                <SparkleIcon className='w-4 h-4 text-slate-500' />
                            )}
                            Answer
                        </h2>

                        <div className='text-slate-500 font-light'>
                            {isLoading ? (
                                <SkeletonLoader />
                            ) : (
                                <AnswerMarkdown markdown={agentState?.answer?.markdown} /> //👈🏼 displays search results
                            )}
                        </div>
                    </div>

                    {agentState?.answer?.references?.length && (
                        <div className='flex col-span-12 lg:col-span-4 flex-col gap-y-4 w-[200px]'>
                            <h2 className='flex items-center gap-x-2'>
                                <BookOpenIcon className='w-4 h-4 text-slate-500' />
                                References
                            </h2>
                            <ul className='text-slate-900 font-light text-sm flex flex-col gap-y-2'>
                                {agentState?.answer?.references?.map(
                                    (ref: any, idx: number) => (
                                        <li key={idx}>
                                            <a
                                                href={ref.url}
                                                target='_blank'
                                                rel='noopener noreferrer'
                                            >
                                                {idx + 1}. {ref.title}
                                            </a>
                                        </li>
                                    )
                                )}
                            </ul>
                        </div>
                    )}
                </div>
            </div>
        </motion.div>
    );
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه کد بالا نتایج جستجو را از وضعیت عامل بازیابی می کند و آنها را با استفاده از useCoAgent قلاب نتایج جستجو در قالب علامت گذاری برگردانده می شوند و به قسمت ارسال می شوند AnswerMarkdown کامپوننت، که محتوا را در صفحه نمایش می دهد.

در نهایت قطعه کد زیر را در قسمت کپی کنید AnswerMarkdown جزء با استفاده از کتابخانه React Markdown، محتوای علامت گذاری شده به صورت متن فرمت شده ارائه می شود.

import Markdown from "react-markdown";

export function AnswerMarkdown({ markdown }: { markdown: string }) {
    return (
        <div className='markdown-wrapper'>
            <Markdown>{markdown}</Markdown>
        </div>
    );
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کامپوننت ResultsView

تبریک می گویم! شما پروژه این آموزش را تکمیل کرده اید. همچنین می توانید فیلم ضبط شده را در اینجا مشاهده کنید:

ضبط کامل وبینار


پیچیدن آن

هوش LLM زمانی مؤثرتر است که در کنار هوش انسانی کار کند و CopilotKit CoAgents به شما امکان می دهد عوامل هوش مصنوعی، خلبانان و انواع مختلف دستیارها را در برنامه های نرم افزاری خود تنها در چند دقیقه ادغام کنید.

اگر نیاز به ساخت یک محصول هوش مصنوعی یا ادغام عوامل هوش مصنوعی در برنامه خود دارید، باید CopilotKit را در نظر بگیرید.

کد منبع این آموزش در GitHub موجود است:

https://github.com/CopilotKit/CopilotKit/tree/main/examples/coagents-ai-researcher

با تشکر از شما برای خواندن!

نوشته های مشابه

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

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا