444 lines
21 KiB
Python
444 lines
21 KiB
Python
import os, sys, json
|
||
from loguru import logger
|
||
src_dir = os.path.join(
|
||
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||
)
|
||
sys.path.append(src_dir)
|
||
|
||
from configs.model_config import KB_ROOT_PATH, JUPYTER_WORK_PATH, CB_ROOT_PATH
|
||
from configs.server_config import SANDBOX_SERVER
|
||
from coagent.llm_models.llm_config import EmbedConfig, LLMConfig
|
||
|
||
from coagent.connector.phase import BasePhase
|
||
from coagent.connector.agents import BaseAgent
|
||
from coagent.connector.schema import Message
|
||
from coagent.codechat.codebase_handler.codebase_handler import CodeBaseHandler
|
||
|
||
import importlib
|
||
from loguru import logger
|
||
|
||
|
||
from coagent.tools import CodeRetrievalSingle, RelatedVerticesRetrival, Vertex2Code
|
||
|
||
# 定义一个新的agent类
|
||
class CodeRetrieval(BaseAgent):
|
||
|
||
def start_action_step(self, message: Message) -> Message:
|
||
'''do action before agent predict '''
|
||
# 根据问题获取代码片段和节点信息
|
||
action_json = CodeRetrievalSingle.run(message.code_engine_name, message.origin_query, llm_config=self.llm_config, embed_config=self.embed_config, search_type="tag",
|
||
local_graph_path=message.local_graph_path, use_nh=message.use_nh)
|
||
current_vertex = action_json['vertex']
|
||
message.customed_kargs["Code Snippet"] = action_json["code"]
|
||
message.customed_kargs['Current_Vertex'] = current_vertex
|
||
|
||
# 获取邻近节点
|
||
action_json = RelatedVerticesRetrival.run(message.code_engine_name, message.customed_kargs['Current_Vertex'])
|
||
# 获取邻近节点所有代码
|
||
relative_vertex = []
|
||
retrieval_Codes = []
|
||
for vertex in action_json["vertices"]:
|
||
# 由于代码是文件级别,所以相同文件代码不再获取
|
||
# logger.debug(f"{current_vertex}, {vertex}")
|
||
current_vertex_name = current_vertex.replace("#", "").replace(".java", "" ) if current_vertex.endswith(".java") else current_vertex
|
||
if current_vertex_name.split("#")[0] == vertex.split("#")[0]: continue
|
||
|
||
action_json = Vertex2Code.run(message.code_engine_name, vertex)
|
||
if action_json["code"]:
|
||
retrieval_Codes.append(action_json["code"])
|
||
relative_vertex.append(vertex)
|
||
#
|
||
message.customed_kargs["Retrieval_Codes"] = retrieval_Codes
|
||
message.customed_kargs["Relative_vertex"] = relative_vertex
|
||
return message
|
||
|
||
|
||
# add agent or prompt_manager class
|
||
agent_module = importlib.import_module("coagent.connector.agents")
|
||
setattr(agent_module, 'CodeRetrieval', CodeRetrieval)
|
||
|
||
|
||
|
||
llm_config = LLMConfig(
|
||
model_name="gpt-4", api_key=os.environ["OPENAI_API_KEY"],
|
||
api_base_url=os.environ["API_BASE_URL"], temperature=0.3
|
||
)
|
||
embed_config = EmbedConfig(
|
||
embed_engine="model", embed_model="text2vec-base-chinese",
|
||
embed_model_path=os.path.join(src_dir, "embedding_models/text2vec-base-chinese")
|
||
)
|
||
|
||
## initialize codebase
|
||
# delete codebase
|
||
codebase_name = 'client_local'
|
||
code_path = "D://chromeDownloads/devopschat-bot/client_v2/client"
|
||
use_nh = False
|
||
cbh = CodeBaseHandler(codebase_name, code_path, crawl_type='dir', use_nh=use_nh, local_graph_path=CB_ROOT_PATH,
|
||
llm_config=llm_config, embed_config=embed_config)
|
||
cbh.delete_codebase(codebase_name=codebase_name)
|
||
|
||
|
||
# load codebase
|
||
codebase_name = 'client_local'
|
||
code_path = "D://chromeDownloads/devopschat-bot/client_v2/client"
|
||
use_nh = True
|
||
do_interpret = True
|
||
cbh = CodeBaseHandler(codebase_name, code_path, crawl_type='dir', use_nh=use_nh, local_graph_path=CB_ROOT_PATH,
|
||
llm_config=llm_config, embed_config=embed_config)
|
||
cbh.import_code(do_interpret=do_interpret)
|
||
|
||
|
||
cbh = CodeBaseHandler(codebase_name, code_path, crawl_type='dir', use_nh=use_nh, local_graph_path=CB_ROOT_PATH,
|
||
llm_config=llm_config, embed_config=embed_config)
|
||
vertexes = cbh.search_vertices(vertex_type="class")
|
||
|
||
|
||
# log-level,print prompt和llm predict
|
||
os.environ["log_verbose"] = "0"
|
||
|
||
phase_name = "code2Tests"
|
||
phase = BasePhase(
|
||
phase_name, sandbox_server=SANDBOX_SERVER, jupyter_work_path=JUPYTER_WORK_PATH,
|
||
embed_config=embed_config, llm_config=llm_config, kb_root_path=KB_ROOT_PATH,
|
||
)
|
||
|
||
# round-1
|
||
logger.debug(vertexes)
|
||
test_cases = []
|
||
for vertex in vertexes:
|
||
query_content = f"为{vertex}生成可执行的测例 "
|
||
query = Message(
|
||
role_name="human", role_type="user",
|
||
role_content=query_content, input_query=query_content, origin_query=query_content,
|
||
code_engine_name=codebase_name, score_threshold=1.0, top_k=3, cb_search_type="tag",
|
||
use_nh=use_nh, local_graph_path=CB_ROOT_PATH,
|
||
)
|
||
output_message, output_memory = phase.step(query, reinit_memory=True)
|
||
# print(output_memory.to_str_messages(return_all=True, content_key="parsed_output_list"))
|
||
print(output_memory.get_spec_parserd_output())
|
||
values = output_memory.get_spec_parserd_output()
|
||
test_code = {k:v for i in values for k,v in i.items() if k in ["SaveFileName", "Test Code"]}
|
||
test_cases.append(test_code)
|
||
|
||
os.makedirs(f"{CB_ROOT_PATH}/tests", exist_ok=True)
|
||
|
||
with open(f"{CB_ROOT_PATH}/tests/{test_code['SaveFileName']}", "w") as f:
|
||
f.write(test_code["Test Code"])
|
||
break
|
||
|
||
|
||
|
||
|
||
# import os, sys, json
|
||
# from loguru import logger
|
||
# src_dir = os.path.join(
|
||
# os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||
# )
|
||
# sys.path.append(src_dir)
|
||
|
||
# from configs.model_config import KB_ROOT_PATH, JUPYTER_WORK_PATH, CB_ROOT_PATH
|
||
# from configs.server_config import SANDBOX_SERVER
|
||
# from coagent.tools import toLangchainTools, TOOL_DICT, TOOL_SETS
|
||
# from coagent.llm_models.llm_config import EmbedConfig, LLMConfig
|
||
|
||
# from coagent.connector.phase import BasePhase
|
||
# from coagent.connector.agents import BaseAgent
|
||
# from coagent.connector.chains import BaseChain
|
||
# from coagent.connector.schema import (
|
||
# Message, Memory, load_role_configs, load_phase_configs, load_chain_configs, ActionStatus
|
||
# )
|
||
# from coagent.connector.memory_manager import BaseMemoryManager
|
||
# from coagent.connector.configs import AGETN_CONFIGS, CHAIN_CONFIGS, PHASE_CONFIGS, BASE_PROMPT_CONFIGS
|
||
# from coagent.connector.prompt_manager.prompt_manager import PromptManager
|
||
# from coagent.codechat.codebase_handler.codebase_handler import CodeBaseHandler
|
||
|
||
# import importlib
|
||
# from loguru import logger
|
||
|
||
# # 下面给定了一份代码片段,以及来自于它的依赖类、依赖方法相关的代码片段,你需要判断是否为这段指定代码片段生成测例。
|
||
# # 理论上所有代码都需要写测例,但是受限于人的精力不可能覆盖所有代码
|
||
# # 考虑以下因素进行裁剪:
|
||
# # 功能性: 如果它实现的是一个具体的功能或逻辑,则通常需要编写测试用例以验证其正确性。
|
||
# # 复杂性: 如果代码较为,尤其是包含多个条件判断、循环、异常处理等的代码,更可能隐藏bug,因此应该编写测试用例。如果代码涉及复杂的算法或者逻辑,那么编写测试用例可以帮助确保逻辑的正确性,并在未来的重构中防止引入错误。
|
||
# # 关键性: 如果它是关键路径的一部分或影响到核心功能,那么它就需要被测试。对于核心业务逻辑或者系统的关键组件,应当编写全面的测试用例来确保功能的正确性和稳定性。
|
||
# # 依赖性: 如果代码有外部依赖,可能需要编写集成测试或模拟这些依赖进行单元测试。
|
||
# # 用户输入: 如果代码处理用户输入,尤其是来自外部的、非受控的输入,那么创建测试用例来检查输入验证和处理是很重要的。
|
||
# # 频繁更改:对于经常需要更新或修改的代码,有相应的测试用例可以确保更改不会破坏现有功能。
|
||
|
||
|
||
# # 代码公开或重用:如果代码将被公开或用于其他项目,编写测试用例可以提高代码的可信度和易用性。
|
||
|
||
|
||
# # update new agent configs
|
||
# judgeGenerateTests_PROMPT = """#### Agent Profile
|
||
# When determining the necessity of writing test cases for a given code snippet,
|
||
# it's essential to evaluate its interactions with dependent classes and methods (retrieved code snippets),
|
||
# in addition to considering these critical factors:
|
||
# 1. Functionality: If it implements a concrete function or logic, test cases are typically necessary to verify its correctness.
|
||
# 2. Complexity: If the code is complex, especially if it contains multiple conditional statements, loops, exceptions handling, etc.,
|
||
# it's more likely to harbor bugs, and thus test cases should be written.
|
||
# If the code involves complex algorithms or logic, then writing test cases can help ensure the accuracy of the logic and prevent errors during future refactoring.
|
||
# 3. Criticality: If it's part of the critical path or affects core functionalities, then it needs to be tested.
|
||
# Comprehensive test cases should be written for core business logic or key components of the system to ensure the correctness and stability of the functionality.
|
||
# 4. Dependencies: If the code has external dependencies, integration testing may be necessary, or mocking these dependencies during unit testing might be required.
|
||
# 5. User Input: If the code handles user input, especially from unregulated external sources, creating test cases to check input validation and handling is important.
|
||
# 6. Frequent Changes: For code that requires regular updates or modifications, having the appropriate test cases ensures that changes do not break existing functionalities.
|
||
|
||
# #### Input Format
|
||
|
||
# **Code Snippet:** the initial Code or objective that the user wanted to achieve
|
||
|
||
# **Retrieval Code Snippets:** These are the associated code segments that the main Code Snippet depends on.
|
||
# Examine these snippets to understand how they interact with the main snippet and to determine how they might affect the overall functionality.
|
||
|
||
# #### Response Output Format
|
||
# **Action Status:** Set to 'finished' or 'continued'.
|
||
# If set to 'finished', the code snippet does not warrant the generation of a test case.
|
||
# If set to 'continued', the code snippet necessitates the creation of a test case.
|
||
|
||
# **REASON:** Justify the selection of 'finished' or 'continued', contemplating the decision through a step-by-step rationale.
|
||
# """
|
||
|
||
# generateTests_PROMPT = """#### Agent Profile
|
||
# As an agent specializing in software quality assurance,
|
||
# your mission is to craft comprehensive test cases that bolster the functionality, reliability, and robustness of a specified Code Snippet.
|
||
# This task is to be carried out with a keen understanding of the snippet's interactions with its dependent classes and methods—collectively referred to as Retrieval Code Snippets.
|
||
# Analyze the details given below to grasp the code's intended purpose, its inherent complexity, and the context within which it operates.
|
||
# Your constructed test cases must thoroughly examine the various factors influencing the code's quality and performance.
|
||
|
||
# ATTENTION: response carefully referenced "Response Output Format" in format.
|
||
|
||
# Each test case should include:
|
||
# 1. clear description of the test purpose.
|
||
# 2. The input values or conditions for the test.
|
||
# 3. The expected outcome or assertion for the test.
|
||
# 4. Appropriate tags (e.g., 'functional', 'integration', 'regression') that classify the type of test case.
|
||
# 5. these test code should have package and import
|
||
|
||
# #### Input Format
|
||
|
||
# **Code Snippet:** the initial Code or objective that the user wanted to achieve
|
||
|
||
# **Retrieval Code Snippets:** These are the interrelated pieces of code sourced from the codebase, which support or influence the primary Code Snippet.
|
||
|
||
# #### Response Output Format
|
||
# **SaveFileName:** construct a local file name based on Question and Context, such as
|
||
|
||
# ```java
|
||
# package/class.java
|
||
# ```
|
||
|
||
|
||
# **Test Code:** generate the test code for the current Code Snippet.
|
||
# ```java
|
||
# ...
|
||
# ```
|
||
|
||
# """
|
||
|
||
# CODE_GENERATE_TESTS_PROMPT_CONFIGS = [
|
||
# {"field_name": 'agent_profile', "function_name": 'handle_agent_profile', "is_context": False},
|
||
# # {"field_name": 'tool_information',"function_name": 'handle_tool_data', "is_context": False},
|
||
# {"field_name": 'context_placeholder', "function_name": '', "is_context": True},
|
||
# # {"field_name": 'reference_documents', "function_name": 'handle_doc_info'},
|
||
# {"field_name": 'session_records', "function_name": 'handle_session_records'},
|
||
# {"field_name": 'code_snippet', "function_name": 'handle_code_snippet'},
|
||
# {"field_name": 'retrieval_codes', "function_name": 'handle_retrieval_codes', "description": ""},
|
||
# {"field_name": 'output_format', "function_name": 'handle_output_format', 'title': 'Response Output Format', "is_context": False},
|
||
# {"field_name": 'begin!!!', "function_name": 'handle_response', "is_context": False, "omit_if_empty": False}
|
||
# ]
|
||
|
||
|
||
# class CodeRetrievalPM(PromptManager):
|
||
# def handle_code_snippet(self, **kwargs) -> str:
|
||
# if 'previous_agent_message' not in kwargs:
|
||
# return ""
|
||
# previous_agent_message: Message = kwargs['previous_agent_message']
|
||
# code_snippet = previous_agent_message.customed_kargs.get("Code Snippet", "")
|
||
# current_vertex = previous_agent_message.customed_kargs.get("Current_Vertex", "")
|
||
# instruction = "the initial Code or objective that the user wanted to achieve"
|
||
# return instruction + "\n" + f"name: {current_vertex}\n{code_snippet}"
|
||
|
||
# def handle_retrieval_codes(self, **kwargs) -> str:
|
||
# if 'previous_agent_message' not in kwargs:
|
||
# return ""
|
||
# previous_agent_message: Message = kwargs['previous_agent_message']
|
||
# Retrieval_Codes = previous_agent_message.customed_kargs["Retrieval_Codes"]
|
||
# Relative_vertex = previous_agent_message.customed_kargs["Relative_vertex"]
|
||
# instruction = "the initial Code or objective that the user wanted to achieve"
|
||
# s = instruction + "\n" + "\n".join([f"name: {vertext}\n{code}" for vertext, code in zip(Relative_vertex, Retrieval_Codes)])
|
||
# return s
|
||
|
||
|
||
|
||
# AGETN_CONFIGS.update({
|
||
# "CodeJudger": {
|
||
# "role": {
|
||
# "role_prompt": judgeGenerateTests_PROMPT,
|
||
# "role_type": "assistant",
|
||
# "role_name": "CodeJudger",
|
||
# "role_desc": "",
|
||
# "agent_type": "CodeRetrieval"
|
||
# # "agent_type": "BaseAgent"
|
||
# },
|
||
# "prompt_config": CODE_GENERATE_TESTS_PROMPT_CONFIGS,
|
||
# "prompt_manager_type": "CodeRetrievalPM",
|
||
# "chat_turn": 1,
|
||
# "focus_agents": [],
|
||
# "focus_message_keys": [],
|
||
# },
|
||
# "generateTests": {
|
||
# "role": {
|
||
# "role_prompt": generateTests_PROMPT,
|
||
# "role_type": "assistant",
|
||
# "role_name": "generateTests",
|
||
# "role_desc": "",
|
||
# "agent_type": "CodeRetrieval"
|
||
# # "agent_type": "BaseAgent"
|
||
# },
|
||
# "prompt_config": CODE_GENERATE_TESTS_PROMPT_CONFIGS,
|
||
# "prompt_manager_type": "CodeRetrievalPM",
|
||
# "chat_turn": 1,
|
||
# "focus_agents": [],
|
||
# "focus_message_keys": [],
|
||
# },
|
||
# })
|
||
# # update new chain configs
|
||
# CHAIN_CONFIGS.update({
|
||
# "codeRetrievalChain": {
|
||
# "chain_name": "codeRetrievalChain",
|
||
# "chain_type": "BaseChain",
|
||
# "agents": ["CodeJudger", "generateTests"],
|
||
# "chat_turn": 1,
|
||
# "do_checker": False,
|
||
# "chain_prompt": ""
|
||
# }
|
||
# })
|
||
|
||
# # update phase configs
|
||
# PHASE_CONFIGS.update({
|
||
# "codeGenerateTests": {
|
||
# "phase_name": "codeGenerateTests",
|
||
# "phase_type": "BasePhase",
|
||
# "chains": ["codeRetrievalChain"],
|
||
# "do_summary": False,
|
||
# "do_search": False,
|
||
# "do_doc_retrieval": False,
|
||
# "do_code_retrieval": False,
|
||
# "do_tool_retrieval": False,
|
||
# },
|
||
# })
|
||
|
||
|
||
# role_configs = load_role_configs(AGETN_CONFIGS)
|
||
# chain_configs = load_chain_configs(CHAIN_CONFIGS)
|
||
# phase_configs = load_phase_configs(PHASE_CONFIGS)
|
||
|
||
|
||
# from coagent.tools import CodeRetrievalSingle, RelatedVerticesRetrival, Vertex2Code
|
||
|
||
# # 定义一个新的agent类
|
||
# class CodeRetrieval(BaseAgent):
|
||
|
||
# def start_action_step(self, message: Message) -> Message:
|
||
# '''do action before agent predict '''
|
||
# # 根据问题获取代码片段和节点信息
|
||
# action_json = CodeRetrievalSingle.run(message.code_engine_name, message.origin_query, llm_config=self.llm_config, embed_config=self.embed_config, search_type="tag",
|
||
# local_graph_path=message.local_graph_path, use_nh=message.use_nh)
|
||
# current_vertex = action_json['vertex']
|
||
# message.customed_kargs["Code Snippet"] = action_json["code"]
|
||
# message.customed_kargs['Current_Vertex'] = current_vertex
|
||
|
||
# # 获取邻近节点
|
||
# action_json = RelatedVerticesRetrival.run(message.code_engine_name, message.customed_kargs['Current_Vertex'])
|
||
# # 获取邻近节点所有代码
|
||
# relative_vertex = []
|
||
# retrieval_Codes = []
|
||
# for vertex in action_json["vertices"]:
|
||
# # 由于代码是文件级别,所以相同文件代码不再获取
|
||
# # logger.debug(f"{current_vertex}, {vertex}")
|
||
# current_vertex_name = current_vertex.replace("#", "").replace(".java", "" ) if current_vertex.endswith(".java") else current_vertex
|
||
# if current_vertex_name.split("#")[0] == vertex.split("#")[0]: continue
|
||
|
||
# action_json = Vertex2Code.run(message.code_engine_name, vertex)
|
||
# if action_json["code"]:
|
||
# retrieval_Codes.append(action_json["code"])
|
||
# relative_vertex.append(vertex)
|
||
# #
|
||
# message.customed_kargs["Retrieval_Codes"] = retrieval_Codes
|
||
# message.customed_kargs["Relative_vertex"] = relative_vertex
|
||
# return message
|
||
|
||
|
||
# # add agent or prompt_manager class
|
||
# agent_module = importlib.import_module("coagent.connector.agents")
|
||
# prompt_manager_module = importlib.import_module("coagent.connector.prompt_manager")
|
||
|
||
# setattr(agent_module, 'CodeRetrieval', CodeRetrieval)
|
||
# setattr(prompt_manager_module, 'CodeRetrievalPM', CodeRetrievalPM)
|
||
|
||
|
||
# # log-level,print prompt和llm predict
|
||
# os.environ["log_verbose"] = "0"
|
||
|
||
# phase_name = "codeGenerateTests"
|
||
# llm_config = LLMConfig(
|
||
# model_name="gpt-4", api_key=os.environ["OPENAI_API_KEY"],
|
||
# api_base_url=os.environ["API_BASE_URL"], temperature=0.3
|
||
# )
|
||
# embed_config = EmbedConfig(
|
||
# embed_engine="model", embed_model="text2vec-base-chinese",
|
||
# embed_model_path=os.path.join(src_dir, "embedding_models/text2vec-base-chinese")
|
||
# )
|
||
|
||
# ## initialize codebase
|
||
# # delete codebase
|
||
# codebase_name = 'client_local'
|
||
# code_path = "D://chromeDownloads/devopschat-bot/client_v2/client"
|
||
# use_nh = False
|
||
# cbh = CodeBaseHandler(codebase_name, code_path, crawl_type='dir', use_nh=use_nh, local_graph_path=CB_ROOT_PATH,
|
||
# llm_config=llm_config, embed_config=embed_config)
|
||
# cbh.delete_codebase(codebase_name=codebase_name)
|
||
|
||
|
||
# # load codebase
|
||
# codebase_name = 'client_local'
|
||
# code_path = "D://chromeDownloads/devopschat-bot/client_v2/client"
|
||
# use_nh = True
|
||
# do_interpret = True
|
||
# cbh = CodeBaseHandler(codebase_name, code_path, crawl_type='dir', use_nh=use_nh, local_graph_path=CB_ROOT_PATH,
|
||
# llm_config=llm_config, embed_config=embed_config)
|
||
# cbh.import_code(do_interpret=do_interpret)
|
||
|
||
|
||
# cbh = CodeBaseHandler(codebase_name, code_path, crawl_type='dir', use_nh=use_nh, local_graph_path=CB_ROOT_PATH,
|
||
# llm_config=llm_config, embed_config=embed_config)
|
||
# vertexes = cbh.search_vertices(vertex_type="class")
|
||
|
||
# phase = BasePhase(
|
||
# phase_name, sandbox_server=SANDBOX_SERVER, jupyter_work_path=JUPYTER_WORK_PATH,
|
||
# embed_config=embed_config, llm_config=llm_config, kb_root_path=KB_ROOT_PATH,
|
||
# )
|
||
|
||
# # round-1
|
||
# logger.debug(vertexes)
|
||
# test_cases = []
|
||
# for vertex in vertexes:
|
||
# query_content = f"为{vertex}生成可执行的测例 "
|
||
# query = Message(
|
||
# role_name="human", role_type="user",
|
||
# role_content=query_content, input_query=query_content, origin_query=query_content,
|
||
# code_engine_name=codebase_name, score_threshold=1.0, top_k=3, cb_search_type="tag",
|
||
# use_nh=use_nh, local_graph_path=CB_ROOT_PATH,
|
||
# )
|
||
# output_message, output_memory = phase.step(query, reinit_memory=True)
|
||
# # print(output_memory.to_str_messages(return_all=True, content_key="parsed_output_list"))
|
||
# print(output_memory.get_spec_parserd_output())
|
||
# values = output_memory.get_spec_parserd_output()
|
||
# test_code = {k:v for i in values for k,v in i.items() if k in ["SaveFileName", "Test Code"]}
|
||
# test_cases.append(test_code)
|
||
|
||
# os.makedirs(f"{CB_ROOT_PATH}/tests", exist_ok=True)
|
||
|
||
# with open(f"{CB_ROOT_PATH}/tests/{test_code['SaveFileName']}", "w") as f:
|
||
# f.write(test_code["Test Code"]) |