1.wow-agent

wow-agent是自塾(zishu.co)出品的开源多智能体框架,目的是尽量减少依赖库,致力于在代码行数和依赖库数量之间取得均衡的最小值,用最划算的方式帮助您在本地搭建AI Agent,嵌入到您的生产工作环节中。
项目链接:wow-agent

2.Agent

概念
1)Agent(智能体)是指能够感知环境并采取行动以实现目标的实体,通常具备自主性、反应性、目标导向和社交能力。(deepseek)
2)在**多智能体系统(Multi-Agent Systems, MAS)**中,代理是指系统中的一个个体智能体,这些智能体能够与其他智能体合作或竞争以实现特定目标。每个代理可以在一个共享环境中做出独立决策,但它们之间可能需要协作或者竞争以达成系统的全局目标。(chatgpt-4o)

总结一下,Agents是生成式AI模型的进阶形态,它们能够利用工具与外界交互,并根据目标进行自主决策和行动,具有更广泛的应用范围和更强大的能力。但同时注意到不是说所有的情况都需要agent,大部分情况下只使用足够大的大模型就足够了,不要手里有锤子就去找钉子。Agent和RAG的区别在于Agent 主要关注自主决策和任务执行,能够与环境进行动态交互,是一种执行智能任务的实体。
RAG 则是通过检索信息增强生成模型的能力,提升生成内容的准确性和丰富性,特别适用于需要知识丰富性的生成任务。

更多概念参考:
1)https://drive.google.com/file/d/1oEjiRCTbd54aSdB_eEe3UShxLBWK9xkt/view
2)https://www.datawhale.cn/learn/content/86/3056

2.手搓一个Agent

2.1 环境配置

使用conda创建并激活虚拟环境:

conda create -n agent python=3.11
conda activate agent

安装依赖

 pip install openai python-dotenv

2.2选择合适的模型

国内模型可以是智谱、Yi、千问deepseek等等。需要三样东西:

  • 第一:一个api_key,这个需要到各家的开放平台上去申请(要保密哦~)
  • 第二:一个base_url,这个需要到各家的开放平台上去拷贝
  • 第三:对话模型名称
    获得这三样后将它们写入.env文件(在主目录下创建)
ZISHU_API_KEY=sk-CheAFXpUwl7euofb660f9269E3Af4609BdFfF426E57d46A5
BASE_URL= "https://open.bigmodel.cn/api/paas/v4/"
CHAT_MODEL= "glm-4-flash"

2.2 读取配置并构造client

import os
from dotenv import load_dotenv
from openai import OpenAI
from prompt import sys_prompt, registered_prompt, query_prompt, delete_prompt  
from openai import OpenAI
# 加载环境变量
load_dotenv()
# 从环境变量中读取api_key
api_key = os.getenv('ZISHU_API_KEY')
base_url = os.getenv('base_url')
chat_model = os.getenv('chat_model')

client = OpenAI(
    api_key = api_key,
    base_url = base_url
)

2.3设计prompt

sys_prompt = """你是一个聪明的客服。您将能够根据用户的问题将不同的任务分配给不同的人。您有以下业务线:
1.用户注册。如果用户想要执行这样的操作,您应该发送一个带有"registered workers"的特殊令牌。并告诉用户您正在调用它。
2.用户数据查询。如果用户想要执行这样的操作,您应该发送一个带有"query workers"的特殊令牌。并告诉用户您正在调用它。
3.删除用户数据。如果用户想执行这种类型的操作,您应该发送一个带有"delete workers"的特殊令牌。并告诉用户您正在调用它。
"""
registered_prompt = """
您的任务是根据用户信息存储数据。您需要从用户那里获得以下信息:
1.用户名、性别、年龄
2.用户设置的密码
3.用户的电子邮件地址
如果用户没有提供此信息,您需要提示用户提供。如果用户提供了此信息,则需要将此信息存储在数据库中,并告诉用户注册成功。
存储方法是使用SQL语句。您可以使用SQL编写插入语句,并且需要生成用户ID并将其返回给用户。
如果用户没有新问题,您应该回复带有 "customer service" 的特殊令牌,以结束任务。
"""
query_prompt = """
您的任务是查询用户信息。您需要从用户那里获得以下信息:
1.用户ID
2.用户设置的密码
如果用户没有提供此信息,则需要提示用户提供。如果用户提供了此信息,那么需要查询数据库。如果用户ID和密码匹配,则需要返回用户的信息。
如果用户没有新问题,您应该回复带有 "customer service" 的特殊令牌,以结束任务。
"""
delete_prompt = """
您的任务是删除用户信息。您需要从用户那里获得以下信息:
1.用户ID
2.用户设置的密码
3.用户的电子邮件地址
如果用户没有提供此信息,则需要提示用户提供该信息。
如果用户提供了这些信息,则需要查询数据库。如果用户ID和密码匹配,您需要通知用户验证码已发送到他们的电子邮件,需要进行验证。
如果用户没有新问题,您应该回复带有 "customer service" 的特殊令牌,以结束任务。
"""

可以直接放在主文件里或者新建一个文件导入也可以。

2.4 定义智能客服智能体

class SmartAssistant:
    def __init__(self):
        self.client = client 

        self.system_prompt = sys_prompt
        self.registered_prompt = registered_prompt
        self.query_prompt = query_prompt
        self.delete_prompt = delete_prompt

        # Using a dictionary to store different sets of messages
        self.messages = {
            "system": [{"role": "system", "content": self.system_prompt}],
            "registered": [{"role": "system", "content": self.registered_prompt}],
            "query": [{"role": "system", "content": self.query_prompt}],
            "delete": [{"role": "system", "content": self.delete_prompt}]
        }

        # Current assignment for handling messages
        self.current_assignment = "system"

    def get_response(self, user_input):
        self.messages[self.current_assignment].append({"role": "user", "content": user_input})
        while True:
            response = self.client.chat.completions.create(
                model=chat_model,
                messages=self.messages[self.current_assignment],
                temperature=0.9,
                stream=False,
                max_tokens=2000,
            )

            ai_response = response.choices[0].message.content
            if "registered workers" in ai_response:
                self.current_assignment = "registered"
                print("意图识别:",ai_response)
                print("switch to <registered>")
                self.messages[self.current_assignment].append({"role": "user", "content": user_input})
            elif "query workers" in ai_response:
                self.current_assignment = "query"
                print("意图识别:",ai_response)
                print("switch to <query>")
                self.messages[self.current_assignment].append({"role": "user", "content": user_input})
            elif "delete workers" in ai_response:
                self.current_assignment = "delete"
                print("意图识别:",ai_response)
                print("switch to <delete>")
                self.messages[self.current_assignment].append({"role": "user", "content": user_input})
            elif "customer service" in ai_response:
                print("意图识别:",ai_response)
                print("switch to <customer service>")
                self.messages["system"] += self.messages[self.current_assignment]
                self.current_assignment = "system"
                return ai_response
            else:
                self.messages[self.current_assignment].append({"role": "assistant", "content": ai_response})
                return ai_response

    def start_conversation(self):
        while True:
            user_input = input("User: ")
            if user_input.lower() in ['exit', 'quit']:
                print("Exiting conversation.")
                break
            response = self.get_response(user_input)
            print("Assistant:", response)

2.5启动

assistant = SmartAssistant()
assistant.start_conversation()

2.6 运行

在这里插入图片描述

3.OpenAI实现阅卷智能体

环境配置和构造client和上面一致不赘述

3.1 定义阅卷智能体

import json
import re


def extract_json_content(text):
    # 这个函数的目标是提取大模型输出内容中的json部分,并对json中的换行符、首位空白符进行删除
    text = text.replace("\n","")
    pattern = r"```json(.*?)```"
    matches = re.findall(pattern, text, re.DOTALL)
    if matches:
        return matches[0].strip()
    return text

class JsonOutputParser:
    def parse(self, result):
        # 这个函数的目标是把json字符串解析成python对象
        # 其实这里写的这个函数性能很差,经常解析失败,有很大的优化空间
        try:
            result = extract_json_content(result)
            parsed_result = json.loads(result)
            return parsed_result
        except json.JSONDecodeError as e:
            raise Exception(f"Invalid json output: {result}") from e

class GradingOpenAI:
    def __init__(self):
        self.model = "glm-4-flash"
        self.output_parser = JsonOutputParser()
        self.template = """你是一位中国专利代理师考试阅卷专家,
						擅长根据给定的题目和答案为考生生成符合要求的评分和中文评语,
						并按照特定的格式输出。
						你的任务是,根据我输入的考题和答案,针对考生的作答生成评分和中文的评语,并以JSON格式返回。
						阅卷标准适当宽松一些,只要考生回答出基本的意思就应当给分。
						答案如果有数字标注,含义是考生如果答出这个知识点,这道题就会得到几分。
						生成的中文评语需要能够被json.loads()这个函数正确解析。
						生成的整个中文评语需要用英文的双引号包裹,在被包裹的字符串内部,请用中文的双引号。
						中文评语中不可以出现换行符、转义字符等等。
						
						输出格式为JSON:
						{{
						  "llmgetscore": 0,
						  "llmcomments": "中文评语"
						}}
						
						比较学生的回答与正确答案,
						并给出满分为10分的评分和中文评语。 
						题目:{ques_title} 
						答案:{answer} 
						学生的回复:{reply}"""

    def create_prompt(self, ques_title, answer, reply):
        return self.template.format(
            ques_title=ques_title,
            answer=answer,
            reply=reply
        )

    def grade_answer(self, ques_title, answer, reply):
        success = False
        while not success:
            # 这里是一个不得已的权宜之计
            # 上面的json解析函数不是表现很差吗,那就多生成几遍,直到解析成功
            # 对大模型生成的内容先解析一下,如果解析失败,就再让大模型生成一遍
            try:
                response = client.chat.completions.create(
                    model=self.model,
                    messages=[
                        {"role": "system", "content": "你是一位专业的考试阅卷专家。"},
                        {"role": "user", "content": self.create_prompt(ques_title, answer, reply)}
                    ],
                    temperature=0.7
                )

                result = self.output_parser.parse(response.choices[0].message.content)
                success = True
            except Exception as e:
                print(f"Error occurred: {e}")
                continue

        return result['llmgetscore'], result['llmcomments']

    def run(self, input_data):
        output = []
        for item in input_data:
            score, comment = self.grade_answer(
                item['ques_title'], 
                item['answer'], 
                item['reply']
            )
            item['llmgetscore'] = score
            item['llmcomments'] = comment
            output.append(item)
        return output
grading_openai = GradingOpenAI()

3.2输入数据和运行输出

# 示例输入数据
input_data = [
 {'ques_title': '请解释共有技术特征、区别技术特征、附加技术特征、必要技术特征的含义',
  'answer': '共有技术特征:与最接近的现有技术共有的技术特征(2.5分); 区别技术特征:区别于最接近的现有技术的技术特征(2.5分); 附加技术特征:对所引用的技术特征进一步限定的技术特征,增加的技术特征(2.5分); 必要技术特征:为解决其技术问题所不可缺少的技术特征(2.5分)。',
  'fullscore': 10,
  'reply': '共有技术特征:与所对比的技术方案相同的技术特征\n区别技术特征:与所对比的技术方案相区别的技术特征\n附加技术特征:对引用的技术特征进一步限定的技术特征\n必要技术特征:解决技术问题必须可少的技术特征'},
 {'ques_title': '请解释前序部分、特征部分、引用部分、限定部分',
  'answer': '前序部分:独权中,主题+与最接近的现有技术共有的技术特征,在其特征在于之前(2.5分); 特征部分:独权中,与区别于最接近的现有技术的技术特征,在其特征在于之后(2.5分);引用部分:从权中引用的权利要求编号及主题 (2.5分);限定部分:从权中附加技术特征(2.5分)。',
  'fullscore': 10,
  'reply': '前序部分:独立权利要求中与现有技术相同的技术特征\n特征部分:独立权利要求中区别于现有技术的技术特征\n引用部分:从属权利要求中引用其他权利要求的部分\n限定部分:对所引用的权利要求进一步限定的技术特征'}]

graded_data = grading_openai.run(input_data)
print(graded_data)

结果
在这里插入图片描述

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐