提交版本

This commit is contained in:
CakeCN
2025-01-02 09:29:49 +08:00
parent eb67bcfb70
commit a1904afbc8
137 changed files with 1906 additions and 885 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
from typing import Any, Callable, Optional, Union, Sequence
from loguru import logger
from agent.flex_service_toolkit import FlexServiceToolkit
from agentscope.exception import ResponseParsingError, FunctionCallError
from agentscope.agents import AgentBase
from agentscope.memory.temporary_memory import TemporaryMemory
from agentscope.message import Msg
from agentscope.parsers import MarkdownJsonDictParser
from agentscope.service.service_toolkit import ServiceFunction
from agentscope.service import (
ServiceToolkit,
ServiceResponse,
ServiceExecStatus,
)
import json
INSTRUCTION_SCORE_PROMPT_CN = """
你是一名经验丰富的算法课程评分专家,你的任务是:基于学生对一个章节的学习日志、对话流,按照指定的评分标准进行评分。
但是不同于普通老师,为了提高得分的区分度,你需要作为一名非常挑剔的专家,根据评分标准仔细挑剔学生的学习日志,并给出评分报告。
重要的挑剔点:
1. 存在错误的概念理解
2. 存在矛盾的概念理解
3. 存在不清晰、不连贯的概念表达
4. 其他你认为可以挑剔的地方
下面是学生的整个学习日志和对话流:
"""
CHAPTER_HINT_CN ="""
上面就是学生的整个学习日志和对话流,请进行下面的各条章节评分标准进行挑剔与评分。
"""
RESPONSE_HINT_CN = """
你的返回必须包含:
对于每条章节评分标准,报告学生的得分以及挑剔的结果。
例如:
```
{'评分标准1': {'得分': 8, '挑剔报告': '答案正确但对于xxx概念表述有误'}
}
```
"""
INSTRUCTION_SCORE_PROMPT_EN = """
You are a experienced algorithm course scoring expert, your task is to: Based on the students' learning logs and dialogues, score them according to the specified scoring standard.
But unlike a normal teacher, to improve the distinction of the score, you need to be a very critical expert, carefully pick out the students' learning logs according to the scoring standard and give a score report.
The important points to pick out:
1. There are errors in the concept understanding
2. There are contradictions in the concept understanding
3. There are unclear, incoherent concept expressions
4. Other places you think can be picked out
Below is the students' entire learning log and dialogue:
"""
CHAPTER_HINT_EN = """
Above is the students' entire learning log and dialogue, please pick out according to the following chapter scoring standard and score them.
"""
RESPONSE_HINT_EN="""
Your response must contain:
For each chapter scoring standard, report the students' score and pick out the results.
For example:
```
{'Score standard 1': {'Score': 8, 'Pick out report': 'The answer is correct, but for the xxx concept expression is wrong'}
}
```
"""
class ScoreAgent(AgentBase):
"""
ScoreAgent is a agent that can score students' learning logs.
"""
def __init__(self, name: str, model_config_name: str, memory: TemporaryMemory,
chapter_score_prompt: str,
service_toolkit: ServiceToolkit,
sys_prompt: str = "You're a helpful assistant.",
max_iters: int = 5,
verbose: bool = True,
**kwargs):
self.service_toolkit = service_toolkit
super().__init__(
name=name,
sys_prompt=sys_prompt,
model_config_name=model_config_name,
)
self.max_iters = max_iters
self.verbose = verbose
if not sys_prompt.endswith("\n"):
sys_prompt = sys_prompt + "\n"
self.sys_prompt = "\n".join(
[
# The brief intro of the role and target
sys_prompt.format(name=self.name),
# The detailed instruction prompt for the agent
INSTRUCTION_SCORE_PROMPT_CN,
],
)
self.memory = TemporaryMemory()
self.memory.add(Msg("system", self.sys_prompt, role="system"))
self.memory.add(memory.get_memory())
self.memory.add(Msg("system", CHAPTER_HINT_CN, role="system"))
self.memory.add(Msg("system", chapter_score_prompt, role="system"))
self.memory.add(Msg("system", RESPONSE_HINT_CN, role="system"))
self.parser = MarkdownJsonDictParser(
content_hint={
"thought": "what you thought",
"speak": "actual response in correct format mentioned above",
},
required_keys=["thought", "speak"],
# Only print the speak field when verbose is False
keys_to_content=True if self.verbose else "speak",
)
def reply(self, x = None, user_backboard = ""):
for _ in range(self.max_iters):
if self.verbose:
self.speak(f" ITER {_+1} ".center(70, "#"))
try:
hint_msg = Msg(
"system",
self.parser.format_instruction+"\n",
role="system",
echo=self.verbose,
)
prompt = self.model.format(self.memory.get_memory(),hint_msg
)
if self.verbose:
self.speak(f"API Trigger".center(70, "#"))
self.speak(str(prompt))
res = self.model(
prompt,
parse_func=self.parser.parse,
max_retries=2,
######################
)
if self.verbose:
self.speak(f"Result Parsed".center(70, "#"))
self.speak(str(res.parsed))
print(res.parsed)
self.memory.add(
Msg(
self.name,
self.parser.to_memory(res.parsed),
"assistant",
),
)
msg_returned = Msg(
self.name,
self.parser.to_content(res.parsed),
"assistant",
)
return msg_returned
except ResponseParsingError as e:
# Print out raw response from models for developers to debug
response_msg = Msg(self.name, e.raw_response, "assistant")
self.speak(response_msg)
# Re-correct by model itself
error_msg = Msg("system", str(e), "system")
self.speak(error_msg)
self.memory.add([response_msg, error_msg])
except Exception as e:
self.speak(f"Error: {e}".center(70, "#"))
self.speak(f"Retrying".center(70, "#"))
continue
return Msg(self.name, "Error: Max iterations reached", "assistant")

View File

@@ -0,0 +1,152 @@
from typing import Any, Callable, Optional, Union, Sequence
from loguru import logger
from agent.flex_service_toolkit import FlexServiceToolkit
from agentscope.exception import ResponseParsingError, FunctionCallError
from agentscope.agents import AgentBase
from agentscope.memory.temporary_memory import TemporaryMemory
from agentscope.message import Msg
from agentscope.parsers import MarkdownJsonDictParser
from agentscope.service.service_toolkit import ServiceFunction
from agentscope.service import (
ServiceToolkit,
ServiceResponse,
ServiceExecStatus,
)
import json
INSTRUCTION_TOTAL_SCORE_PROMPT_CN = """
你是一名精通文件处理的专家,你的本次任务非常简单,给你一段由其他老师给出的评分评价,你需要从中提取每一条标准下的得分,并计算总分,返回总分即可。
"""
RESPONSE_TOTAL_SCORE_HINT_CN = """
你的返回必须包含且仅包含一个整数,表示得分。
例如:
输入:
```
{'评分标准1': {'得分': 8, '挑剔报告': '答案正确但对于xxx概念表述有误'},
'评分标准2': {'得分': 3, '挑剔报告': '答案错误对于xxx概念理解完全错误导致回答有误'}
}
```
输出:
11
下面是真正的输入:
"""
INSTRUCTION_TOTAL_SCORE_PROMPT_EN = """
You are an expert in file processing. Your task is very simple. You will be given a segment of evaluation comments provided by another teacher. You need to extract the scores for each criterion and calculate the total score, returning only the total score.
"""
RESPONSE_TOTAL_SCORE_HINT_EN="""
Your return must contain and only contain an integer representing the score. For example:
Input:
```
{'Criterion 1': {'Score': 8, 'Critical Report': 'The answer is correct, but there is a mistake in the explanation of the xxx concept'},
'Criterion 2': {'Score': 3, 'Critical Report': 'The answer is incorrect, with a complete misunderstanding of the xxx concept, leading to an incorrect response'}
}
```
Output:
```
{'output': 11}
```
Below is the actual input:
"""
class TotalScoreAgent(AgentBase):
"""
TotalScoreAgent is a agent that can gather students' all score.
"""
def __init__(self, name: str, model_config_name: str, input: str,
service_toolkit: ServiceToolkit,
sys_prompt: str = "You're a helpful assistant.",
max_iters: int = 5,
verbose: bool = True,
**kwargs):
self.service_toolkit = service_toolkit
super().__init__(
name=name,
sys_prompt=sys_prompt,
model_config_name=model_config_name,
)
self.max_iters = max_iters
self.verbose = verbose
if not sys_prompt.endswith("\n"):
sys_prompt = sys_prompt + "\n"
self.sys_prompt = "\n".join(
[
# The brief intro of the role and target
sys_prompt.format(name=self.name),
# The detailed instruction prompt for the agent
INSTRUCTION_TOTAL_SCORE_PROMPT_CN,
RESPONSE_TOTAL_SCORE_HINT_CN
],
)
self.memory = TemporaryMemory()
self.memory.add(Msg("system", self.sys_prompt, role="system"))
self.memory.add(Msg("User", input, role="system"))
self.parser = MarkdownJsonDictParser(
content_hint={
"output": "total score",
},
required_keys=["output"],
# Only print the speak field when verbose is False
keys_to_content=True if self.verbose else "speak",
)
def reply(self, x = None, user_backboard = ""):
for _ in range(self.max_iters):
if self.verbose:
self.speak(f" ITER {_+1} ".center(70, "#"))
try:
hint_msg = Msg(
"system",
self.parser.format_instruction+"\n",
role="system",
echo=self.verbose,
)
prompt = self.model.format(self.memory.get_memory(),hint_msg
)
if self.verbose:
self.speak(f"API Trigger".center(70, "#"))
self.speak(str(prompt))
res = self.model(
prompt,
parse_func=self.parser.parse,
max_retries=2,
######################
)
print('====-======-=====')
return res.parsed['output']
if self.verbose:
self.speak(f"Result Parsed".center(70, "#"))
self.speak(str(res))
print(res)
return res
except ResponseParsingError as e:
# Print out raw response from models for developers to debug
response_msg = Msg(self.name, e.raw_response, "assistant")
self.speak(response_msg)
# Re-correct by model itself
error_msg = Msg("system", str(e), "system")
self.speak(error_msg)
self.memory.add([response_msg, error_msg])
except Exception as e:
self.speak(f"Error: {e}".center(70, "#"))
self.speak(f"Retrying".center(70, "#"))
continue
return Msg(self.name, "Error: Max iterations reached", "assistant")

View File

@@ -1,235 +1,329 @@
import sys
import os
current_directory = os.path.dirname(os.path.abspath(__file__))
sys.path.append(current_directory)
import agentscope
from agentscope.message import Msg
import os
import asyncio
import threading
import json
from agent.flex_service_toolkit import *
from AlgoriAgent.projects.algoriAgent.agent.algori_agent import *
from agentscope.service import (
ServiceToolkit,
ServiceResponse,
ServiceExecStatus,
)
import configparser
config = configparser.ConfigParser()
config.read('config.ini')
openai_api_key = config['Global']['api_key']
OPENAI_CFG_DICT = {
"config_name": "openai_cfg", # 此配置的名称,必须保证唯一
"model_type": "openai_chat", # 模型类型
"model_name": "gpt-4o-mini", # 模型名称
#"model_name": "gpt-4", # 模型名称
#"model_name": "llama3",
"api_key": openai_api_key, # OpenAI API key. 如果没有设置,将使用环境变量中的 OPENAI_API_KEY
"client_args": {
"base_url": config['Global']['base_chat_url']
},
}
import uuid
from AlgoriAgent.projects.algoriAgent.tools.judge_tools import judge
EMPTY_CHAPTER_CHAIN = [ Chapter(1, CHAPTER_FOCUS, "本章是未打开某个具体章节时的默认章节。", "处于本章节时不会有任何章节跳转。请作为一名经验丰富的算法教师,回答用户的问题。") ]
def tool_name_to_tool(tool_name_list):
tools = []
for tool_name in tool_name_list:
if tool_name == "":
continue
if tool_name == "judge":
tools.append(judge)
return tools
class AgentManager:
def __init__(self):
agentscope.init(model_configs=[OPENAI_CFG_DICT])#, studio_url="http://0.0.0.0:5000")
self.agents = {}
def new_agent(self, markdown:str, markdown_prompt:str, score_prompt:str, id = None):
'''
markdown: 教案的markdown文件内容
markdown_prompt: 教案的prompt的markdown文件内容
score_prompt: 评分的prompt的markdown文件内容
根据3个教案的prompt生成一个agent返回agent的id与agent
'''
markdown_list = markdown.split("\n")
markdown_prompt_list = markdown_prompt.split("\n")
score_prompt_list = score_prompt.split("\n")
# 获取 H1 标题
title = ""
for line in markdown_list:
if line.startswith("# "):
title = line[2:]
break
# 对于 H3 标题 构造每一个 Chapter
# 首先找到所有的 H3 标题
chapter_dict = {}
chapter_sequence = []
for line in markdown_list:
if line.startswith("### "):
chapter_name = line[4:]
chapter_dict[chapter_name] = {}
chapter_sequence.append(chapter_name)
# 将 H3 标题 和 其对应的内容 构造成一个 Chapter
h3_name = ""
content = ""
for i in range(len(markdown_list)):
if markdown_list[i].startswith("### "):
if(h3_name != ""):
chapter_dict[h3_name]["markdown"] = content
h3_name = markdown_list[i][4:]
content = ""
continue
if h3_name != "":
content += markdown_list[i]+"\n"
if(h3_name != ""):
chapter_dict[h3_name]["markdown"] = content
h3_name = ""
content = ""
require_tools = []
for i in range(len(markdown_prompt_list)):
if markdown_prompt_list[i].startswith("### "):
if(h3_name != ""):
chapter_dict[h3_name]["markdown_prompt"] = content
chapter_dict[h3_name]["require_tools"] = tool_name_to_tool(require_tools)
h3_name = markdown_prompt_list[i][4:]
content = ""
continue
if h3_name != "":
if markdown_prompt_list[i].startswith("_require_tools"):
require_tools.append(markdown_prompt_list[i].split("=")[1].strip())
continue
content += markdown_prompt_list[i]+"\n"
if(h3_name != ""):
chapter_dict[h3_name]["markdown_prompt"] = content
chapter_dict[h3_name]["require_tools"] = tool_name_to_tool(require_tools)
h3_name = ""
content = ""
for i in range(len(score_prompt_list)):
if score_prompt_list[i].startswith("### "):
if(h3_name != ""):
chapter_dict[h3_name]["score_prompt"] = content
h3_name = score_prompt_list[i][4:]
content = ""
continue
if h3_name != "":
content += score_prompt_list[i]+"\n"
if(h3_name != ""):
chapter_dict[h3_name]["score_prompt"] = content
chapter_chain = []
No = 1
print (chapter_dict)
for chapter_name in chapter_sequence:
chapter_chain.append(Chapter(No, CHAPTER_LATTER, title, chapter_dict[chapter_name]["markdown"], chapter_dict[chapter_name]["markdown_prompt"], chapter_dict[chapter_name]["score_prompt"],chapter_dict[chapter_name]["require_tools"]))
No+=1
chapter_chain[0].Focus()
# Prepare the tools for the agent
service_toolkit = FlexServiceToolkit()
# for tool_function in unity_function_list:
# service_toolkit.add(tool_function)
agent = ChapterChainAgent(
name="assistant",
model_config_name="openai_cfg",
verbose=True,
service_toolkit=service_toolkit,
max_iters=5,
chapter_chain=chapter_chain
)
self.agents[id] = agent
return id, agent
def new_agent_with_chain(self, chapter_chain = None, id = None):
'''
'''
if chapter_chain is None:
chapter_chain = EMPTY_CHAPTER_CHAIN
# Prepare the tools for the agent
service_toolkit = FlexServiceToolkit()
# for tool_function in unity_function_list:
# service_toolkit.add(tool_function)
agent = ChapterChainAgent(
name="assistant",
model_config_name="openai_cfg",
verbose=True,
service_toolkit=service_toolkit,
max_iters=5,
chapter_chain=EMPTY_CHAPTER_CHAIN
)
if id is None: id = uuid.uuid4()
self.agents[id] = agent
return id, agent
def get_agent(self, id=None):
'''
如果在get agent之前没有new agent并用id进行访问就返回一个章节链为空的agent
'''
if id:
if id in self.agents:
return self.agents[id]
self.agents[id] = self.new_agent(id)[1]
else:
id = str(uuid.uuid4())
self.agents[id] = self.new_agent()[1]
return id, self.agents[id]
def invoke(self,id, query, user_backboard):
msg = Msg("user", query, role="user")
return self.agents[id](msg, user_backboard = user_backboard)
import time
if __name__ == '__main__':
# tool_demo = ToolDemo("Lava")
# response = tool_demo.invoke("I want such a Gurouce, when use it, it will be thrown and fly towards the mouse position for a short time, and stop. And will damage Enemy who step on it. I call it Lava Gurouce.")
# print(response)
# Start the WebSocket server in a separate thread
manager = AgentManager()
id, agent = manager.new_agent()
# Main thread logic
try:
# Your code that might be interrupted
while True:
input_data = input("用户:")
print(manager.invoke(id, input_data))
except KeyboardInterrupt:
print("Process interrupted by user.")
# You can add any cleanup code here if needed
finally:
print("Exiting program.")
# Code to run before the program exits
import sys
import os
current_directory = os.path.dirname(os.path.abspath(__file__))
sys.path.append(current_directory)
from flask_socketio import SocketIO, join_room, emit, Namespace
import agentscope
from agentscope.message import Msg
import os
import asyncio
import threading
import json
from agent.flex_service_toolkit import *
from AlgoriAgent.projects.algoriAgent.agent.algori_agent import *
from agentscope.service import (
ServiceToolkit,
ServiceResponse,
ServiceExecStatus,
)
import configparser
config = configparser.ConfigParser()
config.read('config.ini')
openai_api_key = config['Global']['api_key']
OPENAI_CFG_DICT = {
"config_name": "openai_cfg", # 此配置的名称,必须保证唯一
"model_type": "openai_chat", # 模型类型
"model_name": "gpt-4o-mini", # 模型名称
#"model_name": "gpt-4", # 模型名称
#"model_name": "llama3",
"api_key": openai_api_key, # OpenAI API key. 如果没有设置,将使用环境变量中的 OPENAI_API_KEY
"client_args": {
"base_url": config['Global']['base_chat_url']
},
}
import uuid
from AlgoriAgent.projects.algoriAgent.tools.judge_tools import judge
EMPTY_CHAPTER_CHAIN = [ Chapter(1, CHAPTER_FOCUS, "本章是未打开某个具体章节时的默认章节。", "处于本章节时不会有任何章节跳转。请作为一名经验丰富的算法教师,回答用户的问题。") ]
def tool_name_to_tool(tool_name_list):
tools = []
for tool_name in tool_name_list:
if tool_name == "":
continue
if tool_name == "judge":
tools.append(judge)
return tools
def tool_name_to_tool_with_args(tool_name_list, tool_args_list) -> list[tuple[Callable, dict]]:
tools = []
for tool_name, tool_args in zip(tool_name_list, tool_args_list):
if tool_name == "":
continue
if tool_name == "judge":
tools.append((judge, {"course_id": tool_args[0], "lesson_id": tool_args[1], "name": tool_args[2]}))
return tools
class AgentManager:
def __init__(self,max_iter = 5, app=None, socketio=None):
agentscope.init(model_configs=[OPENAI_CFG_DICT])#, studio_url="http://0.0.0.0:5000")
self.agents = {}
self.max_iter = max_iter
self.agent_to_id = {}
self.app = app
self.socketio = socketio
def new_agent(self, course_id, lesson_id, markdown:str, markdown_prompt:str, score_prompt:str, id = "Defult Assistant", root_path="."):
'''
markdown: 教案的markdown文件内容
markdown_prompt: 教案的prompt的markdown文件内容
score_prompt: 评分的prompt的markdown文件内容
根据3个教案的prompt生成一个agent返回agent的id与agent
'''
markdown_list = markdown.split("\n")
markdown_prompt_list = markdown_prompt.split("\n")
score_prompt_list = score_prompt.split("\n")
# 获取 H1 标题
title = ""
for line in markdown_list:
if line.startswith("# "):
title = line[2:]
break
# 对于 H3 标题 构造每一个 Chapter
# 首先找到所有的 H3 标题
chapter_dict = {}
chapter_sequence = []
for line in markdown_list:
if line.startswith("### "):
chapter_name = line[4:]
chapter_dict[chapter_name] = {}
chapter_sequence.append(chapter_name)
# 将 H3 标题 和 其对应的内容 构造成一个 Chapter
h3_name = ""
content = ""
for i in range(len(markdown_list)):
if markdown_list[i].startswith("### "):
if(h3_name != ""):
chapter_dict[h3_name]["markdown"] = content
h3_name = markdown_list[i][4:]
content = ""
continue
if h3_name != "":
content += markdown_list[i]+"\n"
if(h3_name != ""):
chapter_dict[h3_name]["markdown"] = content
h3_name = ""
content = ""
require_tools = []
require_tools_args = []
for i in range(len(markdown_prompt_list)):
if markdown_prompt_list[i].startswith("### "):
if(h3_name != ""):
chapter_dict[h3_name]["markdown_prompt"] = content
chapter_dict[h3_name]["require_tools"] = tool_name_to_tool_with_args(require_tools, require_tools_args)
h3_name = markdown_prompt_list[i][4:]
content = ""
require_tools=[]
require_tools_args = []
continue
if h3_name != "":
if markdown_prompt_list[i].startswith("_require_tools"):
require_tools.append(markdown_prompt_list[i].split("=")[1].strip().split(",")[0])
require_tools_args.append((markdown_prompt_list[i].split("=")[1].strip().split(",")[1:]))
continue
content += markdown_prompt_list[i]+"\n"
if(h3_name != ""):
chapter_dict[h3_name]["markdown_prompt"] = content
chapter_dict[h3_name]["require_tools"] = tool_name_to_tool_with_args(require_tools, require_tools_args)
h3_name = ""
content = ""
for i in range(len(score_prompt_list)):
if score_prompt_list[i].startswith("### "):
if(h3_name != ""):
chapter_dict[h3_name]["score_prompt"] = content
h3_name = score_prompt_list[i][4:]
content = ""
continue
if h3_name != "":
content += score_prompt_list[i]+"\n"
if(h3_name != ""):
chapter_dict[h3_name]["score_prompt"] = content
chapter_chain = []
No = 1
print (chapter_dict)
for chapter_name in chapter_sequence:
chapter_chain.append(Chapter(course_id, lesson_id, No, CHAPTER_LATTER, chapter_name, chapter_dict[chapter_name]["markdown"], chapter_dict[chapter_name]["markdown_prompt"], chapter_dict[chapter_name]["score_prompt"],chapter_dict[chapter_name]["require_tools"]))
No+=1
chapter_chain[0].Focus()
# Prepare the tools for the agent
service_toolkit = FlexServiceToolkit()
# for tool_function in unity_function_list:
# service_toolkit.add(tool_function)
agent = ChapterChainAgent(
name=id,
model_config_name="openai_cfg",
verbose=True,
service_toolkit=service_toolkit,
max_iters=5,
chapter_chain=chapter_chain,
root_path = root_path,
)
self.agents[id] = agent
self.agent_to_id[agent] = id
agent.agent_manager = self
return id, agent
def message_pass(self, agent, messagetype, message):
id = self.agent_to_id[agent]
print("message_pass", id, messagetype, message)
with self.app.app_context():
try:
self.socketio.emit(messagetype, message, room=id, namespace='/agent')
except Exception as e:
print("message_pass",e)
def system_message(self, message):
with self.app.app_context():
try:
self.socketio.emit('system_message', message, room=id, namespace='/agent')
except Exception as e:
print("ERROR: system_message",e)
def save_chapter_memory(self, agent,course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal):
id = self.agent_to_id[agent]
self.app.my_function.save_chapter_memory(id, course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal)
def new_agent_with_chain(self, chapter_chain = None, id = None):
if chapter_chain is None:
chapter_chain = EMPTY_CHAPTER_CHAIN
# Prepare the tools for the agent
service_toolkit = FlexServiceToolkit()
# for tool_function in unity_function_list:
# service_toolkit.add(tool_function)
agent = ChapterChainAgent(
name="assistant",
model_config_name="openai_cfg",
verbose=True,
service_toolkit=service_toolkit,
max_iters=5,
chapter_chain=EMPTY_CHAPTER_CHAIN
)
if id is None: id = uuid.uuid4()
self.agents[id] = agent
return id, agent
def get_agent(self, id=None):
'''
如果在get agent之前没有new agent并用id进行访问就返回一个章节链为空的agent
'''
if id:
if id in self.agents:
return self.agents[id]
self.agents[id] = self.new_agent(id)[1]
else:
id = str(uuid.uuid4())
self.agents[id] = self.new_agent()[1]
return id, self.agents[id]
def invoke(self,id, query, user_backboard, reset=False):
msg = Msg("user", query, role="user")
agent = self.agents[id]
res = agent(msg, user_backboard=user_backboard)
return res
# 暂时取消生成器的写法
# 假设 agent 是一个生成器
# if reset or not hasattr(agent, '_generator'):
# agent._generator = agent(msg, user_backboard=user_backboard)
# try:
# response = next(agent._generator)
# yield response
# except StopIteration:
# return
def function_call(self, id, arg_function):
agent = self.agents[id]
return agent.function_call(arg_function)
def change_language(self, id, language):
agent = self.agents[id]
agent.change_language(language)
def sample_judge(self, id, bb):
agent = self.agents[id]
with self.app.app_context():
try:
print(bb.get_active_file_reletive_path())
assert bb is not None and bb.active_file_path != "" , "no path specified"
if bb.get_active_file_reletive_path().endswith(".py"):
self.socketio.emit('terminal', {'data': f"python {bb.get_active_file_reletive_path()}"}, room=id, namespace='/vscode')
self.socketio.emit('system_message', "代码试运行尚在建设,推荐直接通过命令行执行!", room=id, namespace='/agent')
else:
self.socketio.emit('system_message', "代码试运行尚仅支持python文件", room=id, namespace='/agent')
except Exception as e:
print(e)
if (str(e) == "no path specified"):
self.socketio.emit("system_message", "未加载IDE文件同步请尝试重新打开IDE文件或刷新页面并确保插件已连接", room=id, namespace='/agent')
def judge(self, id, bb):
agent = self.agents[id]
with self.app.app_context():
try:
if (agent.chapter_chain[agent.chapter_chain_now].append_tools is not None and len(agent.chapter_chain[agent.chapter_chain_now].append_tools)):
for tool, tool_kwargs in agent.chapter_chain[agent.chapter_chain_now].append_tools:
if tool.__name__ == "judge":
print(bb.get_active_file_reletive_path())
assert bb is not None and bb.active_file_path != "" , "no path specified"
if bb.get_active_file_reletive_path().endswith(".py"):
# self.socketio.emit('terminal', {'data': f"python {bb.get_active_file_reletive_path()}"}, room=id, namespace='/vscode')
self.socketio.emit('system_message', "代码评测中,请稍后", room=id, namespace='/agent')
agent.function_call({'name':'judge','arguments':{'filepath': bb.get_active_file_reletive_path()}})
else:
self.socketio.emit('system_message', "代码评测尚仅支持python文件", room=id, namespace='/agent')
else:
with self.app.app_context():
self.socketio.emit("system_message", "本章学习无需评测", room=id, namespace='/agent')
else:
with self.app.app_context():
self.socketio.emit("system_message", "本章学习无需评测", room=id, namespace='/agent')
except Exception as e:
if (str(e) == "no path specified"):
self.socketio.emit("system_message", "未加载IDE文件同步请尝试重新打开IDE文件或刷新页面并确保插件已连接", room=id, namespace='/agent')
import time
if __name__ == '__main__':
manager = AgentManager()
id, agent = manager.new_agent()
# Main thread logic
try:
# Your code that might be interrupted
while True:
input_data = input("用户:")
print(manager.invoke(id, input_data))
except KeyboardInterrupt:
print("Process interrupted by user.")
# You can add any cleanup code here if needed
finally:
print("Exiting program.")
# Code to run before the program exits

View File

@@ -0,0 +1,54 @@
from agentscope.service.service_toolkit import ServiceFunction
from agentscope.service import (
ServiceToolkit,
ServiceResponse,
ServiceExecStatus,
)
import os
def read_file(filepath:str, root_path:str):
"""Read the file and return the content. Remember use 'judge' function if you want to judge file, instead of this function.
Args:
filepath (`str`): The path to the file.
root_path (`str`): The root path of now student's workspace.
Returns:
content (`str`): The content of the file.
"""
# 从books/code_tests/name/中获取所有.in文件
filepath = os.path.join('..', root_path, filepath)
try:
with open(filepath, 'r') as f:
content = f.read()
except Exception as e:
status = ServiceExecStatus.ERROR
content = str(e)
return ServiceResponse(status, (content))
status = ServiceExecStatus.SUCCESS
return ServiceResponse(status, ('```\n'+content+'```\n'))
def write_file(filepath:str, content:str, root_path:str):
"""Write content to the file.
Args:
filepath (`str`): The path to the file.
content (`str`): The content to be written to the file.
root_path (`str`): The root path of now student's workspace.
Returns:
None.
"""
filepath = os.path.join('..', root_path, filepath)
try:
with open(filepath, 'w') as f:
f.write(content)
except Exception as e:
status = ServiceExecStatus.ERROR
return ServiceResponse(status, None)
status = ServiceExecStatus.SUCCESS
return ServiceResponse(status, None)
file_tools = [read_file, write_file]

View File

@@ -1,64 +1,78 @@
from agentscope.service.service_toolkit import ServiceFunction
from agentscope.service import (
ServiceToolkit,
ServiceResponse,
ServiceExecStatus,
)
import os
def judge(filepath:str, name: str):
"""Call this method to judge the student's solution after they have completed the problem.
Args:
filepath (`str`): The path to the file containing the student's solution.
name (`str`): The name of the problem.
Returns:
Report `tuple(int,str)`: The report of the student's solution.
"""
# 从books/code_tests/name/中获取所有.in文件
directory = 'books/code_tests/'+name
# 如果目录不存在,报错
if not os.path.exists(directory):
status = ServiceExecStatus.FAILED
return ServiceResponse(status, f"The name {name} is not found.")
files = os.listdir(directory)
in_files = [file for file in files if file.endswith('.in')]
save_dir = os.path.dirname(filepath)
Report = ""
passed_num=0
failed_num=0
for file in in_files:
os.remove(os.path.join(save_dir, f"_{name}.out"))
cmd = "cat " + os.path.join(directory, file) + " | " + "python " + filepath +" > " + os.path.join(save_dir, f"_{name}.out")
os.system(cmd)
# 比较结果
re = ""
if compare_file(os.path.join(save_dir, f"_{name}.out"), os.path.join(directory, file.replace(".in", ".out"))):
re = "Passed {file}"
passed_num += 1
else:
re = "Failed {file}"
failed_num += 1
Report = Report + re + "\n"
os.remove(os.path.join(save_dir, f"_{name}.out"))
score = int (100 * passed_num / (passed_num + failed_num))
status = ServiceExecStatus.SUCCESS
return ServiceResponse(status, (Report, score))
def compare_file(path1:str, path2:str):
"""
Compare two files and return true if they are the same.
"""
with open(path1, 'r') as f1, open(path2, 'r') as f2:
# 逐行比较
for line1, line2 in zip(f1, f2):
if line1.strip() != line2.strip():
return False
return True
from agentscope.service.service_toolkit import ServiceFunction
from agentscope.service import (
ServiceToolkit,
ServiceResponse,
ServiceExecStatus,
)
import os
def judge(filepath:str, name: str, course_id: str, lesson_id: str, root_path:str):
"""Call this method to judge the student's solution after they have completed the problem.
Args:
filepath (`str`): The path to the file containing the student's solution.
name (`str`): The name of the problem.
course_id (`str`): The id of the course.
lesson_id (`str`): The id of the lesson.
root_path (`str`): The root path of the user's workspace project.
Returns:
Report `tuple(int,str)`: The report of the student's solution.
"""
# 从books/code_tests/name/中获取所有.in文件
directory = 'books/code_tests/'+course_id+'/'+name
# 如果目录不存在,报错
if not os.path.exists(directory):
status = ServiceExecStatus.FAILED
return ServiceResponse(status, f"The name {name} is not found.")
files = os.listdir(directory)
in_files = [file for file in files if file.endswith('.in')]
save_dir = root_path
Report = ""
passed_num=0
failed_num=0
erroroutput = ""
exceptoutput=""
for file in in_files:
file_path = os.path.join(save_dir, f"_{name}.out")
if os.path.exists(file_path):
os.remove(file_path)
with open(file_path, 'w') as ff:
ff.write("")
cmd = "cat " + os.path.join(directory, file) + " | " + "python " + os.path.join(root_path, filepath) +" > " + os.path.join(save_dir, f"_{name}.out")
os.system(cmd)
# 比较结果
re = ""
if compare_file(os.path.join(save_dir, f"_{name}.out"), os.path.join(directory, file.replace(".in", ".out"))):
re = f"Passed {file}"
passed_num += 1
else:
re = f"Failed {file}"
failed_num += 1
with open(os.path.join(directory, file.replace(".in", ".out")),'r') as f: exceptoutput = f.read()
with open(os.path.join(save_dir, f"_{name}.out"),'r') as f: erroroutput = f.read()
Report = Report + re + "\n"
os.remove(os.path.join(save_dir, f"_{name}.out"))
score = int (100 * passed_num / (passed_num + failed_num))
status = ServiceExecStatus.SUCCESS
return ServiceResponse(status, (score, f"评测得分为 {score}, 在 {passed_num + failed_num} 个测试用例中通过了 {passed_num}个。最后一个错误样例期望输出:'{exceptoutput}',但你的输出:'{erroroutput}"))
def compare_file(path1:str, path2:str):
"""
Compare two files and return true if they are the same.
"""
with open(path1, 'r') as f1, open(path2, 'r') as f2:
# 逐行比较
print('-------------------COMPARE-------------------------')
for line1, line2 in zip(f1, f2):
print(line1.strip(), "||",line2.strip())
if line1.strip() != line2.strip():
return False
return True
judge_tools = [judge]