实战教程展示如何用多个工具链在 Next.js 中快速搭建 AI 应用,涵盖完整架构和代码示例。
对于有志成为开发者的人来说,打造一个出色的项目就是最好的简历。
今天,我们将一举两得:我会教你如何构建一款前沿的 AI 应用,它能够根据你的 LinkedIn、GitHub 和 X 资料生成简历与求职信。
这个项目,以及你随后生成的简历,都会让任何雇主眼前一亮。
使用 Next.js、TypeScript 和 Tailwind CSS 构建简历与求职信生成器 Web 应用。
使用 CopilotKit 将 AI 功能集成到简历与求职信生成器中。
使用 Langchain 和 Tavily 抓取你的 LinkedIn、GitHub 或 X 个人资料内容。
CopilotKit 是一个开源的 AI copilot 平台。它让你能够轻松地将强大的 AI 集成到 React 应用中。
ChatBot:能够在应用内执行操作、感知上下文的应用内聊天机器人 💬
CopilotTextArea:支持上下文感知自动补全和内容插入的 AI 文本字段 📝
Co-Agents:能够与应用和用户交互的应用内 AI 智能体 🤖
要充分理解本教程,你需要具备 React 或 Next.js 的基础知识。
构建 AI 简历与求职信生成器需要使用以下工具:
React Markdown——一个 React 组件,可以接收 Markdown 字符串,并将其安全地渲染为 React 元素。
Langchain——提供了一个框架,使 AI 智能体能够搜索 Web、开展研究,并抓取任意主题或链接的内容。
OpenAI API——提供 API 密钥,使你能够使用 ChatGPT 模型执行各种任务。
Tavily AI——一个搜索引擎,使 AI 智能体能够开展研究或抓取数据,并在应用中获取实时知识。
CopilotKit——一个开源 copilot 框架,可用于构建自定义 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
恭喜!现在你已经准备好构建 AI 简历与求职信生成器了。
在本节中,我将带你完成简历与求职信生成器前端的创建过程,并使用静态内容定义生成器的用户界面。
首先,在代码编辑器中前往 /[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 功能了。
在本节中,你将学习如何向简历与求职信生成器添加 AI copilot,并使用 CopilotKit 生成简历和求职信。
CopilotKit 同时提供前端和后端软件包。它们使你能够接入 React 状态,并使用 AI 智能体在后端处理应用数据。
首先,让我们将 CopilotKit React 组件添加到简历与求职信生成器的前端。
在这里,我将带你完成简历与求职信生成器和 CopilotKit 前端的集成过程,从而实现简历与求职信的生成。
首先,使用以下代码片段,在 /src/app/components/Resume.tsx 文件顶部导入 useCopilotReadable 和 useCopilotAction 自定义 Hook。
import { useCopilotAction, useCopilotReadable } from "@copilotkit/react-core";
在 Resume 函数内部、状态变量下方添加以下代码。它使用 useCopilotReadable Hook,将即将生成的简历与求职信作为应用内聊天机器人的上下文。该 Hook 使 copilot 能够读取简历与求职信。
useCopilotReadable({
description: "The user's cover letter.",
value: coverLetter,
});
useCopilotReadable({
description: "The user's resume.",
value: resume,
});
在上述代码下方添加以下代码,它使用 useCopilotAction Hook 设置一个名为 createCoverLetterAndResume 的操作,用于生成简历和求职信。
该操作接收两个名为 coverLetterMarkdown 和 resumeMarkdown 的参数,用于生成简历和求职信。它包含一个处理函数,会根据给定的提示词生成简历和求职信。
在处理函数内部,coverLetter 和 resume 状态会使用新生成的简历与求职信 Markdown 内容进行更新,如下所示。
useCopilotAction(
{
// 定义操作名称
name: "createCoverLetterAndResume",
// 提供操作描述
description: "Create a cover letter and resume for a job application.",
// 定义操作所需的参数
parameters: [
{
// 第一个参数的名称
name: "coverLetterMarkdown",
// 第一个参数的类型
type: "string",
// 第一个参数的描述
description:
"Markdown text for a cover letter to introduce yourself and briefly summarize your professional background.",
// 将第一个参数标记为必需
required: true,
},
{
// 第二个参数的名称
name: "resumeMarkdown",
// 第二个参数的类型
type: "string",
// 第二个参数的描述
description:
"Markdown text for a resume that displays your professional background and relevant skills.",
// 将第二个参数标记为必需
required: true,
},
],
// 定义调用该操作时要执行的处理函数
handler: async ({ coverLetterMarkdown, resumeMarkdown }) => {
// 使用提供的求职信 Markdown 文本更新状态
setCoverLetter(coverLetterMarkdown);
// 使用提供的简历 Markdown 文本更新状态
setResume(resumeMarkdown);
},
},
// 空依赖数组,表示此副作用不依赖任何 props 或状态
[],
);
之后,打开 /[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 包裹 CopilotSidebar 和 Resume 组件,如下所示。CopilotKit 组件指定了 CopilotKit 后端端点的 URL(/api/copilotkit/),而 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 后端的集成。该后端负责处理来自前端的请求,并提供函数调用能力以及 GPT 等多种大语言模型后端。
此外,我们还会集成一个名为 Tavily 的 AI 智能体,它能够抓取 Web 上任意指定链接的内容。
首先,在根目录中创建一个名为 .env.local 的文件。然后将以下环境变量添加到该文件中,用于保存你的 ChatGPT 和 Tavily 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。
要获取 Tavily 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 抓取该个人资料链接中的内容。然后,它会使用这些内容生成简历和求职信。
生成的简历应如下所示。
生成的求职信应如下所示。
恭喜!你已经完成了本教程的项目。
现在,你已经可以构建一个出色的 AI 简历生成器,既能磨炼 AI 应用开发技能,又能简化求职流程!
如果你喜欢这篇文章,请记得点赞并收藏,也欢迎告诉我你希望接下来看到哪些主题。
部分评论可能仅对已登录的访问者可见。登录后即可查看所有评论。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。