多角色AI代理的一次尝试- AI代码助手

本文涉及的产品
NLP自然语言处理_基础版,每接口每天50万次
NLP自然语言处理_高级版,每接口累计50万次
视觉智能开放平台,视频资源包5000点
简介: 本文介绍了一个多角色AI代理系统,用于自动化代码开发过程。系统包括用户接口、需求分析、代码结构设计、代码生成、代码审查和代码执行等角色,通过协调工作实现从需求到代码生成与测试的全流程自动化。使用了qwen2.5 7b模型,展示了AI在软件开发中的潜力。

AI Agent在投资领域比较火爆,代码助手的投资也比较多,单AI Agent,多角色AI Agent逐渐会成为AI应用的方向。最近一个10岁孩子直接使用豆包和两个ChatGPT进行愚公该移山还是该搬家的辩论活动吸引了大家的眼球,用户作为主持人角色指导2个GPT进行正反方辩友进行辩论和1个GPT作为评委进行评价,这个就是典型的多角色AI代理的应用场景,使用了3个GPT,其实一个也可以的,虽然这个活动最终没有达到预期,Chat GPT作为评委的代理,虽然没有评论,但都记录了它“听”到的内容。这个场景是直接使用GPT作为代理的例子,多角色AI Agent打开走向AGI的想象空间。下面以我比较熟悉的领域,尝试实现一个多角色AI代理编写代码的例子。涉及的角色为:

用户UserInterface:输入任务指令,并在任务无法完成时,进行指导,如:修改代码。

需求分析RequirementAnalyzer:针对用户输入的指令进行需求分析。

代码结构ProgramStructure:针对需求,提出合理的代码结构。

编写代码CodeGenerator:根据需求及代码结构和语言设置,编写代码。

代码审查CodeReviewer:针对生成的代码进行代码审查,提出改进意见。

代码执行CodeExecutor:执行审查完成的代码,输出测试结果。

协作交互Coordinator:协作交互逻辑,通过多次迭代完成任务。

本文默认使用的ollama版本的qwen2.5 7b模型。

完整代码:
import gradio as gr
import requests
import subprocess
import logging
import json
from io import StringIO
import threading
import time

配置日志记录

log_stream = StringIO()
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(), # 输出到控制台
logging.StreamHandler(log_stream) # 输出到 StringIO 流
]
)

定义RequirementAnalyzer角色

class RequirementAnalyzer:
def init(self, api_url, model):
self.api_url = api_url
self.model = model

def analyze_instruction(self, instruction):
    messages = [
        {"role": "system", "content": "你是一个有帮助的助手。"},
        {"role": "user", "content": f"分析以下指令: {instruction}"}
    ]
    response = requests.post(self.api_url, json={"messages": messages, "model": self.model, "stream": True}, stream=True)
    analysis = self.process_stream(response)
    logging.info(f"[RequirementAnalyzer] 分析的需求: {analysis}")
    return analysis

def process_stream(self, response):
    content = ""
    for chunk in response.iter_content(chunk_size=None):
        if chunk:
            chunk_data = chunk.decode('utf-8')
            if "done" in chunk_data:
                chunk_data = chunk_data.split("data: ")[-1]
                chunk_json = json.loads(chunk_data)
                if chunk_json["done"]:
                    break
                else:
                    content += chunk_json["message"]["content"]
    return content

定义ProgramStructure角色

class ProgramStructure:
def init(self, api_url, model):
self.api_url = api_url
self.model = model

def determine_structure(self, requirement):
    messages = [
        {"role": "system", "content": "你是一个有帮助的助手。"},
        {"role": "user", "content": f"确定以下需求的类结构: {requirement}"}
    ]
    response = requests.post(self.api_url, json={"messages": messages, "model": self.model, "stream": True}, stream=True)
    structure = self.process_stream(response)
    logging.info(f"[ProgramStructure] 确定的结构: {structure}")
    return structure

def process_stream(self, response):
    content = ""
    for chunk in response.iter_content(chunk_size=None):
        if chunk:
            chunk_data = chunk.decode('utf-8')
            if "done" in chunk_data:
                chunk_data = chunk_data.split("data: ")[-1]
                chunk_json = json.loads(chunk_data)
                if chunk_json["done"]:
                    break
                else:
                    content += chunk_json["message"]["content"]
    return content

定义CodeGenerator角色

class CodeGenerator:
def init(self, api_url, model):
self.api_url = api_url
self.model = model

def generate_code(self, requirement, structure, language):
    messages = [
        {"role": "system", "content": "你是一个有帮助的助手。"},
        {"role": "user", "content": f"根据以下需求和结构编写{language}代码: {requirement}, {structure}"}
    ]
    response = requests.post(self.api_url, json={"messages": messages, "model": self.model, "stream": True}, stream=True)
    code = self.process_stream(response)
    code = self.extract_code(code)  # 提取代码部分
    logging.info(f"[CodeGenerator] 生成的代码: {code}")
    return code

def process_stream(self, response):
    content = ""
    for chunk in response.iter_content(chunk_size=None):
        if chunk:
            chunk_data = chunk.decode('utf-8')
            if "done" in chunk_data:
                chunk_data = chunk_data.split("data: ")[-1]
                chunk_json = json.loads(chunk_data)
                if chunk_json["done"]:
                    break
                else:
                    content += chunk_json["message"]["content"]
    return content

def extract_code(self, content):
    # 假设代码部分被包裹在 ``` 代码块中,并去掉打头的语言标识
    import re
    match = re.search(r'```.*?\n(.*?)```', content, re.DOTALL)
    if match:
        return match.group(1).strip()
    return content.strip()

定义CodeReviewer角色

class CodeReviewer:
def init(self, api_url, model):
self.api_url = api_url
self.model = model

def review_code(self, code, language):
    messages = [
        {"role": "system", "content": "你是一个有帮助的助手。"},
        {"role": "user", "content": f"审查以下{language}代码并提出改进建议,并给出结论,如:整体来说,这段代码已经很完善: {code}"}
    ]
    response = requests.post(self.api_url, json={"messages": messages, "model": self.model, "stream": True}, stream=True)
    review = self.process_stream(response)
    logging.info(f"[CodeReviewer] 代码审查: {review}")
    return review

def process_stream(self, response):
    content = ""
    for chunk in response.iter_content(chunk_size=None):
        if chunk:
            chunk_data = chunk.decode('utf-8')
            if "done" in chunk_data:
                chunk_data = chunk_data.split("data: ")[-1]
                chunk_json = json.loads(chunk_data)
                if chunk_json["done"]:
                    break
                else:
                    content += chunk_json["message"]["content"]
    return content

定义CodeExecutor角色

class CodeExecutor:
def execute_code(self, code, language):
if language == "Python":
with open("temp.py", "w") as f:
f.write(code)
try:
result = subprocess.run(["python", "temp.py"], capture_output=True, text=True)
logging.info(f"[CodeExecutor] 执行结果: {result.stdout}")
return result.stdout
except Exception as e:
logging.error(f"[CodeExecutor] 执行错误: {e}")
return str(e)
elif language == "JavaScript":
with open("temp.js", "w") as f:
f.write(code)
try:
result = subprocess.run(["node", "temp.js"], capture_output=True, text=True)
logging.info(f"[CodeExecutor] 执行结果: {result.stdout}")
return result.stdout
except Exception as e:
logging.error(f"[CodeExecutor] 执行错误: {e}")
return str(e)
else:
logging.error(f"[CodeExecutor] 不支持的语言")
return "不支持的语言"

定义UserInterface角色

class UserInterface:
def init(self, coordinator):
self.coordinator = coordinator
self.log_output = None

def ai_code_assistant(self, instruction, language, max_attempts):
    return self.coordinator.process_instruction(instruction, language, max_attempts)

def update_logs(self):
    while True:
        time.sleep(1)
        if self.log_output:
            self.log_output.update(value=log_stream.getvalue())

def launch(self):
    with gr.Blocks() as iface:
        gr.Markdown("# AI代码助手")
        with gr.Row():
            with gr.Column():
                instruction = gr.Textbox(label="指令")
                language = gr.Dropdown(["Python", "JavaScript"], label="语言")
                max_attempts = gr.Number(label="最大交互次数", value=5)
                submit_btn = gr.Button("提交")
            with gr.Column():
                with gr.Tabs():
                    with gr.TabItem("生成的代码"):
                        generated_code = gr.Textbox(label="生成的代码", lines=10)
                    with gr.TabItem("程序结构"):
                        program_structure = gr.Textbox(label="程序结构", lines=10)
                    with gr.TabItem("审查结果"):
                        review_result = gr.Textbox(label="审查结果", lines=10)
                    with gr.TabItem("执行结果"):
                        execution_result = gr.Textbox(label="执行结果", lines=10)
                    with gr.TabItem("日志输出"):
                        self.log_output = gr.Textbox(label="日志输出", lines=10)
                    with gr.TabItem("修改代码"):
                        modified_code = gr.Textbox(label="修改代码", lines=10)
                        modify_btn = gr.Button("提交修改")

        submit_btn.click(
            fn=self.ai_code_assistant,
            inputs=[instruction, language, max_attempts],
            outputs=[generated_code, program_structure, review_result, execution_result, self.log_output]
        )

        modify_btn.click(
            fn=self.coordinator.process_modified_code,
            inputs=[modified_code, language],
            outputs=[generated_code, program_structure, review_result, execution_result, self.log_output]
        )

        gr.Examples(
            examples=[
                ["计算一个数的阶乘", "Python", 5],
                ["对一个数字列表按升序排序", "JavaScript", 5]
            ],
            inputs=[instruction, language, max_attempts],
            outputs=[generated_code, program_structure, review_result, execution_result, self.log_output]
        )

        # 启动日志更新线程
        threading.Thread(target=self.update_logs, daemon=True).start()

    iface.launch()

定义Coordinator角色

class Coordinator:
def init(self, requirement_analyzer, program_structure, code_generator, code_reviewer, code_executor):
self.requirement_analyzer = requirement_analyzer
self.program_structure = program_structure
self.code_generator = code_generator
self.code_reviewer = code_reviewer
self.code_executor = code_executor
self.interaction_count = 0
self.max_attempts = 5
self.current_code = None
self.current_language = None
self.continue_after_max_attempts = False

def process_instruction(self, instruction, language, max_attempts):
    self.max_attempts = max_attempts
    self.current_language = language
    self.continue_after_max_attempts = False
    # 分析用户指令
    requirement = self.requirement_analyzer.analyze_instruction(instruction)
    # 确定程序结构
    structure = self.program_structure.determine_structure(requirement)

    # 循环生成和审查代码,直到审查通过或达到最大交互次数
    while self.interaction_count < self.max_attempts or self.continue_after_max_attempts:
        self.interaction_count += 1
        logging.info(f"[Coordinator] 第 {self.interaction_count} 次尝试")
        # 生成代码
        code = self.code_generator.generate_code(requirement, structure, language)
        self.current_code = code
        # 审查代码
        review = self.code_reviewer.review_code(code, language)

        # 如果审查通过,跳出循环
        if "代码已经很完善" in review:
            break

        # 否则,重新生成代码
        requirement = f"修复以下代码: {code}"

    # 如果达到最大交互次数,提示用户修改代码
    if self.interaction_count >= self.max_attempts and not self.continue_after_max_attempts:
        logging.info("[Coordinator] 已达到最大交互次数,任务结束。")
        return code, structure, review, "已达到最大交互次数,任务结束。", self.get_logs()

    # 执行代码
    result = self.code_executor.execute_code(code, language)

    # 检查执行结果,如果发现问题,驱动相关角色行动
    if "Error" in result:
        self.handle_error(code, result)

    return code, structure, review, result, self.get_logs()

def handle_error(self, code, error_message):
    # 这里可以实现错误处理逻辑,例如重新生成代码或提示用户修改代码
    logging.error(f"[Coordinator] 检测到错误: {error_message}")
    logging.info("[Coordinator] 驱动相关角色采取行动...")
    # 提示用户修改代码
    self.current_code = code
    return code, "", "", f"检测到错误,请修改代码: {error_message}", self.get_logs()

def process_modified_code(self, modified_code, language):
    self.current_code = modified_code
    self.continue_after_max_attempts = True
    # 执行修改后的代码
    result = self.code_executor.execute_code(modified_code, language)

    # 检查执行结果,如果发现问题,驱动相关角色行动
    if "Error" in result:
        self.handle_error(modified_code, result)

    return modified_code, "", "", result, self.get_logs()

def get_logs(self):
    # 获取日志输出
    return log_stream.getvalue()

主程序

def main():

# 初始化API URL和模型
api_url = "http://localhost:11434/api/chat"
model = "qwen2.5"

# 创建角色实例
requirement_analyzer = RequirementAnalyzer(api_url, model)
program_structure = ProgramStructure(api_url, model)
code_generator = CodeGenerator(api_url, model)
code_reviewer = CodeReviewer(api_url, model)
code_executor = CodeExecutor()
coordinator = Coordinator(requirement_analyzer, program_structure, code_generator, code_reviewer, code_executor)
user_interface = UserInterface(coordinator)

# 启动用户界面
user_interface.launch()

if name == "main":
main()

首次发表地址:https://blog.csdn.net/wxl781227/article/details/143475737

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
1天前
|
人工智能 UED
VersaGen:生成式 AI 代理,基于 Stable Diffusion 生成图像,专注于控制一至多个视觉主体等生成细节
VersaGen 是一款生成式 AI 代理,专注于文本到图像合成中的视觉控制能力,支持多种视觉控制类型,并通过优化策略提升图像生成质量和用户体验。
20 8
VersaGen:生成式 AI 代理,基于 Stable Diffusion 生成图像,专注于控制一至多个视觉主体等生成细节
|
4月前
|
机器学习/深度学习 人工智能 自然语言处理
构建未来的开发环境:AI 驱动的代码助手
随着人工智能技术的进步,AI驱动的代码助手成为提升软件开发效率和代码质量的关键工具。本文探讨了其潜在功能、技术实现及对未来开发的影响。优势包括自动化任务、实时错误检测、个性化辅助和知识共享。技术上,它结合了机器学习、自然语言处理和深度学习,实现代码理解和推荐、智能补全、自动化测试、代码审查及性能优化等功能,使开发更加高效智能。
|
3月前
|
人工智能 自然语言处理 自动驾驶
阿里云入选Gartner® AI代码助手魔力象限挑战者象限
Gartner发布业界首个AI代码助手魔力象限,全球共12家企业入围,阿里云,成为唯一进入挑战者象限的中国科技公司。对阿里云而言,此次入选代表了其通义灵码在产品功能和市场应用等方面的优秀表现。
|
20天前
|
机器学习/深度学习 人工智能 自然语言处理
DiffSensei:AI 漫画生成框架,能生成内容可控的黑白漫画面板,支持多角色和布局控制
DiffSensei 是一个由北京大学、上海AI实验室及南洋理工大学共同推出的AI漫画生成框架,能够生成可控的黑白漫画面板。该框架整合了基于扩散的图像生成器和多模态大型语言模型(MLLM),支持多角色控制和精确布局控制,适用于漫画创作、个性化内容生成等多个领域。
86 18
DiffSensei:AI 漫画生成框架,能生成内容可控的黑白漫画面板,支持多角色和布局控制
|
21天前
|
人工智能 API 语音技术
TEN Agent:开源的实时多模态 AI 代理框架,支持语音、文本和图像的实时通信交互
TEN Agent 是一个开源的实时多模态 AI 代理框架,集成了 OpenAI Realtime API 和 RTC 技术,支持语音、文本和图像的多模态交互,具备实时通信、模块化设计和多语言支持等功能,适用于智能客服、实时语音助手等多种场景。
123 15
TEN Agent:开源的实时多模态 AI 代理框架,支持语音、文本和图像的实时通信交互
|
29天前
|
存储 人工智能 数据库
Codel:AI代理工具,支持在终端、浏览器、编辑器执行复杂任务和项目
Codel是一款全自主AI代理工具,支持在终端、浏览器和编辑器中执行复杂任务和项目。它运行在沙盒化的Docker环境中,具备自主操作能力,内置浏览器和文本编辑器,所有操作记录存储于PostgreSQL数据库。Codel能够自动完成复杂任务,如创建项目结构、进行网络搜索等,适用于自动化编程、研究与开发、教育与培训以及数据科学与分析等多个领域。
68 11
Codel:AI代理工具,支持在终端、浏览器、编辑器执行复杂任务和项目
|
5天前
|
人工智能 智能硬件
SPAR:智谱 AI 推出自我博弈训练框架,基于生成者和完善者两个角色的互动,提升了执行准确度和自我完善能力
SPAR 是智谱团队推出的自我博弈训练框架,旨在提升大型语言模型在指令遵循方面的能力,通过生成者和完善者的互动以及树搜索技术优化模型响应。
18 0
SPAR:智谱 AI 推出自我博弈训练框架,基于生成者和完善者两个角色的互动,提升了执行准确度和自我完善能力
|
30天前
|
人工智能 自然语言处理 JavaScript
Agent-E:基于 AutoGen 代理框架构建的 AI 浏览器自动化系统
Agent-E 是一个基于 AutoGen 代理框架构建的智能自动化系统,专注于浏览器内的自动化操作。它能够执行多种复杂任务,如填写表单、搜索和排序电商产品、定位网页内容等,从而提高在线效率,减少重复劳动。本文将详细介绍 Agent-E 的功能、技术原理以及如何运行该系统。
84 5
Agent-E:基于 AutoGen 代理框架构建的 AI 浏览器自动化系统
|
4月前
|
存储 人工智能 测试技术
Minstrel自动生成结构化提示,让AI为AI写提示词的多代理提示生成框架
在人工智能迅速发展的背景下,有效利用大型语言模型(LLMs)成为重要议题。9月发布的这篇论文提出了LangGPT结构化提示框架和Minstrel多代理提示生成系统,旨在帮助非AI专家更好地使用LLMs。LangGPT通过模块化设计提高提示的泛化能力和可重用性,Minstrel则通过多代理协作自动生成高质量提示。实验结果显示,这两种方法显著提升了LLMs的性能,特别是在大规模模型上效果显著。
123 2
Minstrel自动生成结构化提示,让AI为AI写提示词的多代理提示生成框架
|
3月前
|
人工智能 自然语言处理 搜索推荐
【通义】AI视界|微软Copilot Studio推出新功能,帮助企业更便捷地构建和部署AI代理
本文介绍了近期科技领域的五大重要动态:马斯克旗下xAI发布首个API,苹果内部研究显示ChatGPT比Siri准确率高25%,微软Copilot Studio推出新功能,霍尼韦尔与谷歌合作引入Gemini AI,浑水创始人建议买入科技七巨头股票。更多资讯请访问【通义】。