阿川私房教材:
學 JavaScript 前端,帶作品集去面試!

63 個專案實戰,寫出作品集,讓面試官眼前一亮!

立即開始免費試讀!

長話短說

對於有抱負的開發人員來說,建立一個偉大的專案是最好的履歷。

好,今天我們就一舉兩得;我將教您如何建立一個由人工智慧驅動的尖端應用程式,該應用程式將根據您的 LinkedIn、GitHub 和 X 生成您的簡歷和求職信。

這個專案和你隨後的簡歷會讓任何雇主驚嘆不已。

圖片描述

我們將介紹如何:

  • 使用 Next.js、TypeScript 和 Tailwind CSS 建立履歷和求職信產生器 Web 應用。

  • 使用 CopilotKit 將 AI 功能整合到履歷和求職信產生器中。

  • 使用 Langchain 和 Tavily 抓取您的 LinkedIn、GitHub 或 X 個人檔案內容。


CopilotKit:用於建立應用內人工智慧副駕駛的開源框架

CopilotKit是一個開源的AI副駕駛平台。我們可以輕鬆地將強大的人工智慧整合到您的 React 應用程式中。

建造:

  • ChatBot:上下文感知的應用內聊天機器人,可以在應用程式內執行操作 💬

  • CopilotTextArea:人工智慧驅動的文字字段,具有上下文感知自動完成和插入功能📝

  • 聯合代理:應用程式內人工智慧代理,可以與您的應用程式和使用者互動🤖

https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3 .amazonaws.com%2Fuploads%2Farticles%2Fx3us3vc140aun0dvrdof.gif

{% cta https://git.new/devtoarticle1 %} Star CopilotKit ⭐️ {% endcta %}


先決條件

要完全理解本教程,您需要對 React 或 Next.js 有基本的了解。

以下是建立人工智慧驅動的履歷和求職信產生器所需的工具:

  • React Markdown - 一個React元件,可以給予一串 Markdown 來安全地渲染到 React 元素。

  • Langchain - 提供了一個框架,使人工智慧代理能夠搜尋網路、研究和抓取任何主題或連結。

  • OpenAI API - 提供 API 金鑰,讓您能夠使用 ChatGPT 模型執行各種任務。

  • Tavily AI - 一種搜尋引擎,使人工智慧代理能夠在應用程式中進行研究或抓取資料並存取即時知識。

  • CopilotKit - 一個開源副駕駛框架,用於建立自訂 AI 聊天機器人、應用程式內 AI 代理程式和文字區域。

專案設定和套件安裝

首先,透過在終端機中執行以下程式碼片段來建立 Next.js 應用程式:

npx create-next-app@latest airesumecoverlettergenerator

選擇您首選的配置設定。在本教學中,我們將使用 TypeScript 和 Next.js App Router。

圖片描述

接下來,安裝 React Markdown 和 OpenAI 套件及其相依性。

npm i react-markdown openai

最後,安裝 CopilotKit 軟體套件。這些套件使我們能夠從 React 狀態檢索資料並將 AI copilot 新增至應用程式。

npm install @copilotkit/react-ui @copilotkit/react-core @copilotkit/backend

恭喜!您現在已準備好建立人工智慧驅動的履歷和求職信產生器。

建立履歷和求職信產生器前端

在本節中,我將引導您完成使用靜態內容建立履歷和求職信產生器前端的過程,以定義生成器的使用者介面。

首先,請在程式碼編輯器中前往/[root]/src/app並建立一個名為components的資料夾。在 Components 資料夾中,建立一個名為Resume.tsx的文件

Resume.tsx檔案中,加入以下程式碼來定義名為Resume的 React 功能元件。

"use client";

// Import React and necessary hooks from the react library
import React from "react";
import { useState } from "react";
// Import the ReactMarkdown component to render markdown content
import ReactMarkdown from "react-markdown";
// Import the Link component from Next.js for navigation
import Link from "next/link";

function Resume() {
  // State variables to store the resume and cover letter content
  const [coverLetter, setCoverLetter] = useState("");
  const [resume, setResume] = useState("");

  return (
    // Main container with flex layout, full width, and minimum height of screen
    <div className="flex flex-col w-full min-h-screen bg-gray-100 dark:bg-gray-800">
      {/* Header section with a fixed height, padding, and border at the bottom */}
      <header className="flex items-center h-16 px-4 border-b shrink-0 md:px-6 bg-white dark:bg-gray-900">
        {/* Link component for navigation with custom styles */}
        <Link
          href="#"
          className="flex items-center gap-2 text-lg font-semibold md:text-base"
          prefetch={false}>
          <span className="sr-only text-gray-500">Resume Dashboard</span>
          <h1>Resume & Cover Letter Generator</h1>
        </Link>
      </header>
      {/* Main content area with padding */}
      <main className="flex-1 p-4 md:p-8 lg:p-10">
        {/* Container for the content with maximum width and centered alignment */}
        <div className="max-w-4xl mx-auto grid gap-8">
          {/* Section for displaying the resume */}
          <section>
            <div className="bg-white dark:bg-gray-900 rounded-lg shadow-sm">
              <div className="p-6 md:p-8">
                <h2 className="text-lg font-bold">Resume</h2>
                <div className="my-6" />
                <div className="grid gap-6">
                  {/* Conditional rendering of the resume content */}
                  {resume ? (
                    <ReactMarkdown>{resume}</ReactMarkdown>
                  ) : (
                    <div>No Resume To Display</div>
                  )}
                </div>
              </div>
            </div>
          </section>
          {/* Section for displaying the cover letter */}
          <section>
            <div className="bg-white dark:bg-gray-900 rounded-lg shadow-sm">
              <div className="p-6 md:p-8">
                <h2 className="text-lg font-bold">Cover Letter</h2>
                <div className="my-6" />
                <div className="grid gap-4">
                  {/* Conditional rendering of the cover letter content */}
                  {coverLetter ? (
                    <ReactMarkdown>{coverLetter}</ReactMarkdown>
                  ) : (
                    <div>No Cover Letter To Display</div>
                  )}
                </div>
              </div>
            </div>
          </section>
        </div>
      </main>
    </div>
  );
}

export default Resume;

接下來,前往/[root]/src/page.tsx文件,並新增以下程式碼來導入Resume元件並定義名為Home的功能元件。

import Resume from "./components/Resume";

export default function Home() {
  return <Resume />;
}

最後,在命令列上執行命令npm run dev ,然後導航到 http://localhost:3000/

現在您應該在瀏覽器上查看履歷和求職信產生器前端,如下所示。

圖片描述

恭喜!現在您已準備好將 AI 功能新增至 AI 支援的履歷和求職信產生器。

使用 CopilotKit 將 AI 功能整合到履歷和求職信產生器

在本節中,您將學習如何將 AI 副駕駛員加入到履歷和求職信產生器,以使用 CopilotKit 產生履歷和求職信。

CopilotKit 提供前端和後端套件。它們使您能夠插入 React 狀態並使用 AI 代理在後端處理應用程式資料。

首先,我們將 CopilotKit React 元件加入履歷和求職信產生器前端。

將 CopilotKit 新增至待辦事項清單產生器前端

在這裡,我將引導您完成將履歷和求職信產生器與 CopilotKit 前端整合的過程,以促進履歷和求職信的產生。

首先,使用下面的程式碼片段導入/src/app/components/Resume.tsx檔案頂部的自訂掛鉤useCopilotReadableuseCopilotAction

import { useCopilotAction, useCopilotReadable } from "@copilotkit/react-core";

Resume函數內的狀態變數下方,加入以下程式碼,該程式碼使用useCopilotReadable掛鉤來新增將作為應用程式內聊天機器人的上下文產生的履歷和求職信。該掛鉤使副駕駛可以閱讀簡歷和求職信。

useCopilotReadable({
    description: "The user's cover letter.",
    value: coverLetter,
  });

  useCopilotReadable({
    description: "The user's resume.",
    value: resume,
  });

在上面的程式碼下方,新增以下程式碼,程式碼使用useCopilotAction掛鉤來設定名為createCoverLetterAndResume的操作,該操作將啟用簡歷和求職信的產生。

操作採用兩個參數,稱為coverLetterMarkdownresumeMarkdown ,用於產生履歷和求職信。它包含一個處理程序函數,可根據給定的提示產生履歷和求職信。

在處理函數內部, coverLetterresume狀態會使用新產生的履歷和求職信 markdown 進行更新,如下所示。

useCopilotAction(
  {
    // Define the name of the action
    name: "createCoverLetterAndResume",
    // Provide a description for the action
    description: "Create a cover letter and resume for a job application.",
    // Define the parameters required for the action
    parameters: [
      {
        // Name of the first parameter
        name: "coverLetterMarkdown",
        // Type of the first parameter
        type: "string",
        // Description of the first parameter
        description:
          "Markdown text for a cover letter to introduce yourself and briefly summarize your professional background.",
        // Mark the first parameter as required
        required: true,
      },
      {
        // Name of the second parameter
        name: "resumeMarkdown",
        // Type of the second parameter
        type: "string",
        // Description of the second parameter
        description:
          "Markdown text for a resume that displays your professional background and relevant skills.",
        // Mark the second parameter as required
        required: true,
      },
    ],
    // Define the handler function to be executed when the action is called
    handler: async ({ coverLetterMarkdown, resumeMarkdown }) => {
      // Update the state with the provided cover letter markdown text
      setCoverLetter(coverLetterMarkdown);
      // Update the state with the provided resume markdown text
      setResume(resumeMarkdown);
    },
  },
  // Empty dependency array, indicating this effect does not depend on any props or state
  [],
);

之後,請前往/[root]/src/app/page.tsx檔案並使用下面的程式碼匯入頂部的 CopilotKit 前端套件和樣式。

import { CopilotKit } from "@copilotkit/react-core";
import { CopilotSidebar } from "@copilotkit/react-ui";
import "@copilotkit/react-ui/styles.css";

然後使用CopilotKit包裝CopilotSidebarResume元件,如下所示。 CopilotKit元件指定 CopilotKit 後端端點 ( /api/copilotkit/ ) 的 URL,而CopilotSidebar則呈現應用程式內聊天機器人,您可以提示您產生履歷和求職信。

export default function Home() {
  return (
    <CopilotKit runtimeUrl="/api/copilotkit">
      <CopilotSidebar
        instructions={"Help the user create a cover letter and resume"}
        labels={{
          initial:
            "Welcome to the cover letter app! Add your LinkedIn, X, or GitHub profile link below.",
        }}
        defaultOpen={true}
        clickOutsideToClose={false}>
        <Resume />
      </CopilotSidebar>
    </CopilotKit>
  );
}

之後,執行開發伺服器並導航至http://localhost:3000 。您應該會看到應用程式內聊天機器人已整合到履歷和求職信產生器中。

圖片描述

將 CopilotKit 後端加入博客

在這裡,我將引導您完成將履歷和求職信產生器與 CopilotKit 後端整合的過程,該後端處理來自前端的請求,並提供函數呼叫和各種 LLM 後端(例如 GPT)。

此外,我們將整合一個名為 Tavily 的人工智慧代理,它可以抓取網路上任何給定連結上的內容。

首先,在根目錄中建立一個名為.env.local的檔案。然後在保存ChatGPTTavily Search API 金鑰的檔案中加入下面的環境變數。


OPENAI_API_KEY="Your ChatGPT API key"
TAVILY_API_KEY="Your Tavily Search API key"
OPENAI_MODEL=gpt-4-1106-preview

若要取得 ChatGPT API 金鑰,請導覽至 https://platform.openai.com/api-keys

圖片描述

若要取得 Tavilly Search API 金鑰,請導覽至 https://app.tavily.com/home

圖片描述

之後,轉到/[root]/src/app並建立一個名為api的資料夾。在api資料夾中,建立一個名為copilotkit的資料夾。

copilotkit資料夾中,建立一個名為tavily.ts的檔案並加入以下程式碼。程式碼定義了一個非同步函數scrape ,它將連結作為輸入,將此連結傳送到 Tavily API,處理 JSON 回應,然後使用 OpenAI 的語言模型以簡單的英文產生回應摘要。

// Import the OpenAI library
import OpenAI from "openai";

// Define an asynchronous function named `scrape` that takes a search query string as an argument
export async function scrape(query: string) {
  // Send a POST request to the specified API endpoint with the search query and other parameters
  const response = await fetch("https://api.tavily.com/search", {
    method: "POST", // HTTP method
    headers: {
      "Content-Type": "application/json", // Specify the request content type as JSON
    },
    body: JSON.stringify({
      api_key: process.env.TAVILY_API_KEY, // API key from environment variables
      query, // The search query passed to the function
      search_depth: "basic", // Search depth parameter
      include_answer: true, // Include the answer in the response
      include_images: false, // Do not include images in the response
      include_raw_content: false, // Do not include raw content in the response
      max_results: 20, // Limit the number of results to 20
    }),
  });

  // Parse the JSON response from the API
  const responseJson = await response.json();

  // Instantiate the OpenAI class
  const openai = new OpenAI();

  // Use the OpenAI API to create a completion based on the JSON response
  const completion = await openai.chat.completions.create({
    messages: [
      {
        role: "system", // Set the role of the message to system
        content: `Summarize the following JSON to answer the research query \`"${query}"\`: ${JSON.stringify(
          responseJson
        )} in plain English.`, // Provide the JSON response to be summarized
      },
    ],
    model: process.env.OPENAI_MODEL || "gpt-4", // Specify the OpenAI model, defaulting to GPT-4 if not set in environment variables
  });

  // Return the content of the first message choice from the completion response
  return completion.choices[0].message.content;
}

接下來,在copilotkit資料夾中建立一個名為route.ts的文件,並加入以下程式碼。程式碼使用 CopilotKit 框架設定抓取操作,以根據給定連結取得和匯總內容。

然後它定義一個呼叫 scrape 函數並傳回結果的操作。如果所需的 API 金鑰可用,它會將此操作新增至 CopilotKit 執行時間,並使用環境變數中指定的 OpenAI 模型回應 POST 請求。

// Import necessary modules and functions
import { CopilotRuntime, OpenAIAdapter } from "@copilotkit/backend";
import { Action } from "@copilotkit/shared";
import { scrape } from "./tavily"; // Import the previously defined scrape function

// Define a scraping action with its name, description, parameters, and handler function
const scrapingAction: Action<any> = {
  name: "scrapeContent", // Name of the action
  description: "Call this function to scrape content from a url in a query.", // Description of the action
  parameters: [
    {
      name: "query", // Name of the parameter
      type: "string", // Type of the parameter
      description:
        "The query for scraping content. 5 characters or longer. Might be multiple words", // Description of the parameter
    },
  ],
  // Handler function to execute when the action is called
  handler: async ({ query }) => {
    console.log("Scraping query: ", query); // Log the query to the console
    const result = await scrape(query); // Call the scrape function with the query and await the result
    console.log("Scraping result: ", result); // Log the result to the console
    return result; // Return the result
  },
};

// Define an asynchronous POST function to handle POST requests
export async function POST(req: Request): Promise<Response> {
  const actions: Action<any>[] = []; // Initialize an empty array to store actions
  // Check if the TAVILY_API_KEY environment variable is set
  if (process.env["TAVILY_API_KEY"]) {
    actions.push(scrapingAction); // Add the scraping action to the actions array
  }
  // Create a new instance of CopilotRuntime with the defined actions
  const copilotKit = new CopilotRuntime({
    actions: actions,
  });

  const openaiModel = process.env["OPENAI_MODEL"]; // Get the OpenAI model from environment variables

  // Return the response from CopilotKit, using the OpenAIAdapter with the specified model
  return copilotKit.response(req, new OpenAIAdapter({ model: openaiModel }));
}

如何產生履歷和求職信

現在轉到您之前整合的應用程式內聊天機器人,加入 LinkedIn、GitHub 或 X 個人資料連結,然後按 Enter 鍵。

在新增連結後,聊天機器人將使用 LangChain 和 Tavily 從連結設定檔中抓取內容。然後它將使用該內容產生履歷和求職信。

產生的簡歷應如下所示。

圖片描述

產生的求職信應如下所示。

圖片描述

恭喜!您已完成本教學的專案。

結論

現在您可以建立一個出色的人工智慧驅動的簡歷產生器,以磨練您的人工智慧建立技能並簡化您的求職過程!

如果您喜歡這篇文章,請記得按讚並保存它,並讓我知道您接下來希望看到哪些主題。


原文出處:https://dev.to/copilotkit/build-an-ai-powered-resume-cover-letter-generator-copilotkit-langchain-tavily-nextjs-1nkc


共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。

阿川私房教材:
學 JavaScript 前端,帶作品集去面試!

63 個專案實戰,寫出作品集,讓面試官眼前一亮!

立即開始免費試讀!