crewAI实践(包含memory的启用)--AiRusumeGenerator

什么是crewAI

Cutting-edge framework for orchestrating role-playing, autonomous AI agents. By fostering collaborative intelligence, CrewAI empowers agents to work together seamlessly, tackling complex tasks.
CrewAI 是一个前沿的框架,用于组织和协调角色扮演的自主AI代理。通过促进协作智能,它使代理能够无缝地协同工作,应对复杂任务。

官网:https://www.crewai.com/

AiRusumeGenerator

ai智能简历在线生成器,一个有点用,但用处不多的多智能体应用。代码在最后。
项目相关文章:
memory的启用,避开openai

功能效果展示

在这里插入图片描述
简历结构设计方案
在这里插入图片描述
求职着目标岗位概况
在这里插入图片描述

开发背景

最近在准备找工作,准备简历是个烦心的事情,恰好在微信公众号看到了crewAI的介绍,又恰好看到官方案例中有简历优化这样一个应用,于是花了一个星期来学习以及使用这款框架,不得不说目前的大模型诞生在国外这一事实造成了很多麻烦,很多AI框架都是围绕着openai开发的。但是,费点力气还是能克服的。

开发步骤

1. 首先得学习下这款框架

这里是学习视频网址。

原理

简单说说我的理解,其原理就是将一个可能比较复杂的任务,比如生成一个简历。。。如果你直接让大模型给你,其实也是可以的,给出的结果有时候可能也还不错,但是就是感觉不是想要的结果,想要改就得不断的修改提示词去调整,才有可能得到想要的结果。
但是懒惰是人的本性,我想要的是我把我的个人信息材料和我目标岗位的信息提供给你,然后你直接给我一份针对性的定制性的简历,最好还能提供一些岗位匹配报告、面试指南等等,这一切都要是针对性的。那么这就是一个复杂的业务流程了。
而复杂的业务流程实现高质量结果的核心就是分工合作,每个人专注自己的事情。据官方提供的信息大模型同样据有此种特性。

由于之前在erp行业干过一年半,所以我对SOP标准作业程序这一概念有所了解,我发现这个概念和crewAI可以说是相当契合了。
于是我们的第一个问题就是,一个简历的标准制作流程是什么?想当然的我认为现在的猎头公司应当有这项任务。什么?没干过猎头,不知道是他有什么业务?很简单,问AI嘛
在这里插入图片描述
好的,流程有了,那么所谓的专人专事,什么人做什么呢?依旧不知道,当然还是问AI:
在这里插入图片描述
好的,应用的基本运行逻辑也就有了,但是一个好的SOP应该每一个关键步骤都有其标准的结果文档才行,那么好,继续问ai:
在这里插入图片描述

ok,到目前为止,一个简历生成器的基本运行逻辑有了,下面就是如何利用crewAI框架去实现了。

大概用法

简单浏览下其官方文档,大概步骤是这样
(1) 解决大模型的使用问题
直接给答案:

from langchain_community.chat_models import ChatZhipuAI,ChatTongyi
import os
#两种大模型,一个是阿里的大模型Qwen,一个是智谱AI的glm4
os.environ["DASHSCOPE_API_KEY"] = ""
os.environ["ZHIPUAI_API_KEY"] = ""

#为memeory的启用而设置,国内用不了openai,也不想用,url是本地部署的xinference服务,兼容openai的api
os.environ['OPENAI_API_BASE'] ="http://localhost:9997/v1"
os.environ['OPENAI_API_KEY'] = 'not empty'


zhipullm = ChatZhipuAI(
    model="glm-4",
    temperature=0.6,
    max_tokens = 4096,
)

TongyiQW = ChatTongyi(
    model="qwen-turbo",
    max_tokens = 4096,
    temperature=0.7
)

# 设个变量好赋值
llm = TongyiQW 

(2) 关键概念,设置agent
这里仅仅展示其中一个,构造可以说是相当简单
其实也展现了一种格式化的提示词写作方法,确定角色、目标、背景,这些就是人类的人设。作为模拟人工智能的大模型也是如此。

# 初始化Agent对象,设置其角色、目标、背景故事以及其他配置
        ICNS = Agent(
            role="信息收集与分析专员",
            goal="深入了解求职者,精准把握职位需求,为简历制作提供详实基础。",
            backstory="1. 作为一家猎头公司求职项目组的信息收集与分析专员,你所在的项目组正在协助求职者准备他的简历。"
            "2. 你将负责通过求职者提供的材料,深入了解其背景、经历、技能及职业目标。"
            "3. 你需要收集并整理求职者提供的所有相关材料,包括现有简历、项目案例、证书等。"
            "4. 你需要深入分析目标职位的详细要求,明确招聘方的偏好和需求。",
            #是否允许智能体生成任务分配给其他智能体
            allow_delegation=False,
            #不使用openai必须单独指定大模型,否则其会默认使用openai
            llm=llm,
            verbose=True,
        )
        

(3) 关键概念,设置task
任务也就是程序步骤,关键在description和expected_output,即任务描述和生成什么样的结果。以及什么人去执行,需要用到什么工具。工具是另一个核心概念。

applicant_analysis = Task(
            name="求职者信息收集与分析",
            description="1. 通过求职者提供的材料,深入了解和分析其背景、经历、技能及职业目标等。"
                "2. 如果在材料中发现有可以打开的url,可以尝试使用网页抓取工具获取更多信息进行分析。"
                "2. 撰写求职者概况报告,要求汇总求职者关键信息。",
            expected_output = "一份详细且准确的Markdown格式的求职者概况报告,汇总求职者关键信息。",
            agent = agent,
            tools = [FileReadTool,scrapeWebsiteTool],
            #将大模型得出的结果存到文件里
            output_file = "result/AiResumeGenerator/求职者概况报告.md",
            #没有文件目录时自动创建
            create_directory=True,
            #异步执行,就是没执行完也可以执行下一个
            async_execution=True,
            
        )

(4) 关键概念,crew
crew是船员的意思,意思是将上面设置的agent与task结合到一起,形成一个完整的团体,也是一个完整的工作流程。

crew = Crew(
    agents=[info_collection_analysis_specialist, resume_architect,content_editor,quality_control_expert,customer_manager],
    tasks=[info_collection_analysis, resume_structure_design,content_creation_filling,content_review_optimization,joint_resume_review],
    verbose=2, # You can set it to 1 or 2 to different logging levels
    memory=True,
    output_log_file = True,
    #据说这里也可以指定代理用什么模型会覆盖agent里面的llm设置
   	#function_calling_llm = zhipullm,
   	#memeory启用时,embeddr也必须启用,不然会默认使用openai
    embedder={
                "provider": "openai",
                "config":{
                #这是通过xinference框架提供的服务,因为在之前设置了openai的baseurl环境变量
                        "model": 'custom-embedding-bge-large-zh-v1.5'
                }
        }
    
)
能够用来做什么?

了解了大体框架原理以及用法,用来能做什么你们心理应该也有数了。
用官方的话来说,这其实是一种新型的编程方式,整个软件运行过程中的每一步,只有软件的流程是确定的(当然开启了层级流程控制,流程也不确定了),输入是模糊的,输出也是模糊的,这里的模糊对比于以前编程函数中的输入和输出,以前我们程序中的每一步骤的数据类型、数据值都是确定的,而crewAI程序不同,只有输入输出的类型是确定的都是字符串,但是值每一次可能都是不同的,这也是ai的魅力所在。
且个人感觉crewAI已经有了半面向自然语言编程的味道了。
最后,出于我狭窄的视野,crewAI能够用来做所有的文字类工作,好像是句废话,但是现在的咨询公司、自媒体等等,都是可以被取代的。

2. 安装crewAI以及使用概述

这里不再赘述,直接引用前辈的贡献。多Agent协作工具CrewAI使用指南

3. 写代码

由于代码长度的问题,agent、task、crew启动单独封装在不同的文件

Agents.py
from crewai import Agent

class Agents():
    """
    Agents class : This class is used to create agents
    function: manager,icns,resume_architect,content_editor,qce,interviewCoach
    """

    def manger(self,llm):
        """
            创建一个表示项目经理的Agent对象,该对象具有特定的角色、目标、背景故事,并允许委托和详细输出。

            参数:
            self: 对象实例,通常在类方法中使用,表示当前类的实例。
            llm: (类型未指定) - 这个参数的用途需要具体上下文来确定,可能是某种管理资源或配置。

            返回:
            manager: Agent对象 - 包含项目经理角色信息的实例,具备管理功能和配置的Agent。

            注意:
            - Agent对象的角色是"项目经理",其目标是高效管理团队并保证任务质量。
            - 背景故事描述了项目经理的角色职责,包括协调团队和确保任务按期高质量完成。
            - 允许代理(allow_delegation=True)意味着该角色可以将部分任务委派给其他对象。
            - 设置为verbose=True,意味着Agent在执行操作时会提供详细的输出信息。
        """
        manager = Agent(
            role="项目经理",
            goal="高效管理团队,确保高质量完成任务",
            backstory="您是一位经验丰富的项目经理,擅长监督复杂项目并引领团队走向成功。您的职责是协调团队成员的努力,确保每项任务按时完成并达到最高标准。",
            allow_delegation=True,
            verbose=True,
            llm = llm,
        )

        return manager
    
    def icns(self, llm):
        """
        创建一个信息收集与分析专员的Agent实例。

        该函数用于初始化一个名为ICNS的Agent对象,该对象将扮演信息收集与分析专员的角色,
        其主要职责是深入了解求职者背景和职位需求,为简历制作提供支持。

        参数:
        - llm: 低层模型的缩写,具体用途未说明,可能是一个用于辅助分析的模型或算法。

        返回:
        - 返回创建的ICNS Agent实例。
        """
        
        # 初始化Agent对象,设置其角色、目标、背景故事以及其他配置
        ICNS = Agent(
            role="信息收集与分析专员",
            goal="深入了解求职者,精准把握职位需求,为简历制作提供详实基础。",
            backstory="1. 作为一家猎头公司求职项目组的信息收集与分析专员,你所在的项目组正在协助求职者准备他的简历。"
            "2. 你将负责通过求职者提供的材料,深入了解其背景、经历、技能及职业目标。"
            "3. 你需要收集并整理求职者提供的所有相关材料,包括现有简历、项目案例、证书等。"
            "4. 你需要深入分析目标职位的详细要求,明确招聘方的偏好和需求。",
            allow_delegation=False,
            llm=llm,
            verbose=True,
        )
        
        return ICNS
    
    def resume_architect(self,llm):
        """
            创建一个代理角色,负责高级简历架构师的工作。
            
            该函数初始化一个Agent对象,配置了该角色的相关属性,如角色名称、目标、背景故事等,
            以及是否允许委托和使用的LLM模型等设置。
            
            参数:
            llm: Large Language Model的缩写,推测是指用于辅助简历设计的语言模型。
            
            返回:
            返回初始化后的Agent对象,该对象代表了高级简历架构师的角色。
        """
        resume_architect = Agent(
            role="高级简历架构师",
            goal="设计简历布局,确保内容结构清晰、吸引眼球,符合求职者身份及目标职位特点。",
            backstory="1. 作为一家猎头公司求职项目组的简历架构师,你所在的项目组正在协助求职者准备他的简历。"
            "2. 你将负责根据信息收集与分析专员的报告,选择最适合求职者的简历模板和结构。"
            "3. 你需要设计简历的整体布局,确保视觉上的吸引力和内容的逻辑性。"
            "4. 你需要制定简历各部分内容的呈现框架,指导内容编辑人员如何组织信息。",
            allow_delegation=False,
            llm=llm,
            verbose=True,
        )
        return resume_architect
    
    def content_editor(self,llm):
        """
            创建一个Agent对象,扮演资深内容编辑师的角色,负责编写高质量的简历内容。
            
            参数:
            llm - 大语言模型的实例,用于协助编辑师生成和优化简历内容。
            
            返回:
            content_editor - 资深内容编辑师的Agent对象,具备特定的角色、目标、背景和行为设置。
        """
        content_editor = Agent(
            role = "资深内容编辑师",
            goal = "编写高质量、针对性强的简历内容,凸显求职者优势,提升简历吸引力。",
            backstory = "1. 作为一家猎头公司求职项目组的内容编辑师,你所在的项目组正在协助求职者准备他的简历。"
            "2. 你需要在简历架构师的指导下,负责不同部分的内容撰写和优化,如个人信息、职业目标、工作经验、项目经历、教育背景、技能清单等。"
            "3. 你需要确保每部分内容精准、突出亮点,符合目标职位的要求。"
            "4. 你需要对接信息收集与分析专员,确保信息的准确性和最新性。",
            allow_delegation=False,
            llm=llm,
            verbose=True,
        )
        return content_editor
    
    def qce(self,llm):
        """
            创建一个质量控制专家代理

            该函数用于初始化并返回一个质量控制专家的角色代理。质量控制专家负责审核简历,
            确保其质量达到高标准,无错误,内容准确且具有专业性和吸引力。

            参数:
            llm (object): 语言模型接口,用于代理与语言模型之间的交互。

            返回:
            Agent: 质量控制专家的角色代理实例。
        """
        quality_control_expert = Agent(
            role = "质量控制专家",
            goal = "严格把关简历质量,保证无错误,内容准确、专业,提升整体表现力。",
            backstory = "1. 作为一家猎头公司求职项目组的质量控制专家,你所在的项目组正在协助求职者准备他的简历。"
            "2. 你需要进行简历的全面审核,包括语法、拼写、逻辑性、语言风格等方面的检查。"
            "3. 你需要确保简历符合行业标准,且具有高度的专业性和吸引力。"
            "4. 你需要协调内容编辑师进行必要的修订,直至达到高标准。",
            allow_delegation=True,
            llm=llm,
            verbose=True,
        )
        return quality_control_expert
    
    def interviewCoach(self,llm):
        """
            创建一个面试辅导顾问的Agent对象,旨在帮助求职者准备面试。

            该顾问将根据求职者的目标职位,提供个性化的面试准备策略,包括公司文化了解、职位要求解析和行业动态把握等方面。

            参数:
                llm: 一个语言模型的实例,用于生成有关面试准备的建议和解答求职者的问题。

            返回:
                一个配置了特定角色、目标、背景故事和行为模式的Agent对象,专注于面试辅导功能。
        """
        interviewCoach = Agent(
            role = "面试辅导顾问",
            goal = "根据目标职位,帮助求职者深入了解公司文化、职位要求及行业动态,准备与职位相关的案例和问题解答。",
            backstory = "1. 作为一家猎头公司求职项目组的面试辅导顾问,你所在的项目组已经完成简历的制作,现在你需要协助求职者准备面试。"
            "2. 你需要根据面试者的简历和目标职位,分析针对该职位的面试准备的要点。"
            "3. 你需要尽可能全面的考虑求职者面试其目标职位时可能遇到的情况。"
            "4. 你需要确保你做的工作能够帮助求职者有更大的机会通过面试。",
            allow_delegation=False,
            llm=llm,
            verbose=True,
        )
        return interviewCoach
    
    
Tasks.py
from crewai import Task
from crewai_tools import ScrapeWebsiteTool
from customtools.BaiduSearch import BaiduSearchTool
from customtools.ChineseFileRead import ChineseFileReadTool


class Tasks():


    def applicant_analysis(self,agent,file_path):
        FileReadTool=ChineseFileReadTool(file_path=file_path)
        scrapeWebsiteTool=ScrapeWebsiteTool()
        applicant_analysis = Task(
            name="求职者信息收集与分析",
            description="1. 通过求职者提供的材料,深入了解和分析其背景、经历、技能及职业目标等。"
                "2. 如果在材料中发现有可以打开的url,可以尝试使用网页抓取工具获取更多信息进行分析。"
                "2. 撰写求职者概况报告,要求汇总求职者关键信息。",
            expected_output = "一份详细且准确的Markdown格式的求职者概况报告,汇总求职者关键信息。",
            agent = agent,
            tools = [FileReadTool,scrapeWebsiteTool],
            output_file = "result/AiResumeGenerator/求职者概况报告.md",
            create_directory=True,
            async_execution=True,
            
        )
        return applicant_analysis
    
    def targetjob_analysis(self,agent,file_path):
        FileReadTool=ChineseFileReadTool(file_path=file_path)
        scrapeWebsiteTool=ScrapeWebsiteTool()
        baiduSearchTool = BaiduSearchTool()
        targetjob_analysis = Task(
            name="求职者目标岗位信息收集与分析",
            description="1. 通过求职者提供的材料,深入了解其目标岗位相关信息,包括但不限于岗位职责、岗位要求、岗位所在行业、目标岗位所在公司概况等。"
                "2. 若目标岗位所在公司信息不足,可以尝试使用网页搜索工具获取更多信息进行分析。"
                "3. 如果在获得的所有信息中发现有可以打开的url,可以尝试使用网页抓取工具获取更多信息进行分析。"
                "4. 根据获得的所有信息,撰写求职者目标岗位概况报告,要求汇总求职者目标岗位关键信息。",
            expected_output = "一份详细且准确的Markdown格式的求职者目标岗位概况报告,汇总求职者目标岗位关键信息。",
            agent = agent,
            tools = [FileReadTool,scrapeWebsiteTool,baiduSearchTool],
            output_file = "result/AiResumeGenerator/求职者目标岗位概况报告.md",
            create_directory=True,
            async_execution=True,
        )
        return targetjob_analysis

    def application_analysis(self,agent,context):
        application_analysis = Task(
            name="求职者与目标职位综合分析",
            description="1. 通过求职者概况报告和求职者目标岗位概况报告联合分析,内容包括但不限于:求职者与目标职位的匹配度、求职者与目标职位的差异性、求职者与目标职位的共性以及求职者简历内容建议。",
            expected_output = "一份详细且准确的Markdown格式的求职者与目标职位综合报告。",
            agent = agent,
            output_file = "result/AiResumeGenerator/求职者与目标职位综合报告.md",
            create_directory=True,
            context = context,
        )

        return application_analysis
    

    def resume_structure_design(self,agent,context):
        resume_structure_design = Task(
            name = "简历结构设计",
            description="1. 根据求职者的职业阶段和目标行业,选择合适的简历模板(如逆向时间顺序、功能性或混合式简历)。"
                "2. 设计清晰、专业的排版,确保简历易于阅读,重点突出。考虑使用清晰的字体、合适的字号、恰当的标题和子标题。"
                "3. 最后根据你完美的设计,撰写简历结构设计方案,包括但不限于简历模板、各部分内容概要及设计说明等。",
            expected_output = "一份Markdown格式的简历结构设计方案,包括但不限于简历模板、各部分内容概要及设计说明等。",
            agent = agent,
            output_file = "result/AiResumeGenerator/简历结构设计方案.md",
            create_directory=True,
            context = context
        )
        
        return resume_structure_design
    

    def writing_resume(self,agent,context):
        content_creation_filling = Task(
            name = "求职者简历制作",
            description="1. 根据简历结构设计方案以及求职者概况报告,编写并填充简历的每个部分,确保内容精确、突出亮点。"
                "2. 撰写简历,确保内容准确、完整、专业且整体符合简历结构设计方案要求。"
                "3. 如果质量控制专家或者高级简历架构师对完成的简历不满意,根据他们的建议进行简历内容的修正和优化。",
            expected_output = "一份精心设计的Markdown格式的个人求职简历。",
            agent = agent,
            output_file = "result/AiResumeGenerator/简历.md",
            create_directory=True,
            context = context,
        )

        return content_creation_filling
    

    def content_review_optimization(self,agent,context):
        content_review_optimization = Task(
            name = "内容审查与优化",
            description="1. 对简历内容进行全面审查,包括语法、拼写、逻辑、表述清晰度及专业术语的正确使用。"
                "2. 与资深内容编辑师和高级简历架构师沟通简历的优化与修正。"
                "3. 撰写内容审查报告,记录所有修改建议、已更正的错误及优化点。",
            expected_output = "一份Markdown格式的简历内容审查报告,记录着所有修改建议及优化点。",
            agent = agent,
            output_file = "result/AiResumeGenerator/简历审查报告.md",
            create_directory=True,
            context = context
        )

        return content_review_optimization
    
    def resume_finalization(self,agent,context):
        resume_finalization = Task(
            name = "简历修订",
            description="1. 根据简历审查报告提供的建议修订简历,完成简历的优化。",
            expected_output = "一份Markdown格式的简历。",
            agent = agent,
            output_file = "result/AiResumeGenerator/简历终稿.md",
            create_directory=True,
            context = context
        )

        return resume_finalization


    def interview_prep(self, agent, context):
        interview_prep = Task(
            name = "面试准备指南制作",
            description="1. 根据求职者与目标职位综合报告和最终修订好的简历,制作面试准备指南。",
            expected_output = "一份精心制作且量身订制的Markdown格式的面试准备指南。",
            agent = agent,
            output_file = "result/AiResumeGenerator/用户面试准备指南.md",
            create_directory=True,
            context = context,
            async_execution=True,
        )

        return interview_prep

mian.py
from Agents import Agents
from Tasks import Tasks
from crewai import Crew,Process
from langchain_community.chat_models import ChatZhipuAI,ChatTongyi
import os
os.environ["DASHSCOPE_API_KEY"] = "******************"
os.environ["ZHIPUAI_API_KEY"] = "**********************"
os.environ['OPENAI_API_BASE'] = 'http://localhost:9997/v1'
os.environ['OPENAI_API_KEY'] = 'not empty'


zhipullm = ChatZhipuAI(
    model="glm-4",
    temperature=0.6,
    max_tokens = 4096,
)

TongyiQW = ChatTongyi(
    model="qwen-turbo",
    max_tokens = 4096,
    temperature=0.7
)

llm = TongyiQW

Agents = Agents()


agent1 = Agents.manger(llm)
agent2 = Agents.icns(llm)
agent3 = Agents.resume_architect(llm)
agent4 = Agents.content_editor(llm)
agent5 = Agents.interviewCoach(llm)
agent6 = Agents.qce(llm)

Tasks = Tasks()
#path_file 指向文件为用户的个人信息文件
task1 = Tasks.applicant_analysis(agent=agent2,file_path=r"D:\crewAI\myagentproject\resource\AiResumeGenerator\custominformation.md")
#这里path_file 指向文件为用户目标岗位的相关信息
task2 = Tasks.targetjob_analysis(agent=agent2,file_path=r"D:\crewAI\myagentproject\resource\AiResumeGenerator\targetjob.txt")
task3 = Tasks.application_analysis(agent=agent2,context=[task1,task2])
task4 = Tasks.resume_structure_design(agent=agent3,context=[task3])
task5 = Tasks.writing_resume(agent=agent4,context=[task4,task1])
task6 = Tasks.content_review_optimization(agent=agent6,context=[task5])
task7 = Tasks.resume_finalization(agent=agent4,context=[task6,task5])
task8 = Tasks.interview_prep(agent=agent5,context=[task3,task7])


crew = Crew(
    agents=[agent2, agent3, agent4, agent5, agent6],
    tasks=[task1, task2, task3, task4, task5, task6, task7, task8],
    verbose=2, # You can set it to 1 or 2 to different logging levels
    memory=True,
    output_log_file = True,
    #function_calling_llm = zhipullm,
    embedder={
                "provider": "openai",
                "config":{
                        "model": 'custom-embedding-bge-large-zh-v1.5'
                }
        },
    share_crew = False,

)


crew.kickoff()
关于task中引入的自定义工具这里不再赘述
  • 37
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朝凡FR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值