Skip to content

Commit 75fbb9a

Browse files
committed
add git function
1 parent de203ee commit 75fbb9a

File tree

8 files changed

+88
-41
lines changed

8 files changed

+88
-41
lines changed

README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,15 @@
2727

2828
## 📰 News
2929

30+
* **September 25th, 2023: The **Git** feature is now available**, enabling the programmer < img src='online_log/static/figures/programmer.png' height=20> to utilize GitHub for version control. To enable this feature, simply set ``"git_management"`` to ``"True"`` in ``ChatChainConfig.json``.
31+
<p align="center">
32+
<img src='./misc/github.png' width=600>
33+
</p>
3034
* September 20th, 2023: The **Human-Agent-Interaction** mode is now available! You can get involved with the ChatDev team by playing the role of reviewer <img src='online_log/static/figures/reviewer.png' height=20> and making suggestions to the programmer <img src='online_log/static/figures/programmer.png' height=20>;
3135
try ``python3 run.py --task [description_of_your_idea] --config "Human"``. See [guide](wiki.md#human-agent-interaction) and [example](WareHouse/Gomoku_HumanAgentInteraction_20230920135038).
32-
<center><img src='misc/Human_intro.png' width=800></center>
36+
<p align="center">
37+
<img src='./misc/Human_intro.png' width=600>
38+
</p>
3339
* September 1st, 2023: The **Art** mode is available now! You can activate the designer agent <img src='online_log/static/figures/designer.png' height=20> to generate images used in the software;
3440
try ``python3 run.py --task [description_of_your_idea] --config "Art"``. See [guide](wiki.md#art) and [example](WareHouse/gomokugameArtExample_THUNLP_20230831122822).
3541
* August 28th, 2023: The system is publicly available.
@@ -165,10 +171,9 @@ create a software package and generate a folder named ``/WareHouse/2048_THUNLP_t
165171

166172
## ⚖️ License
167173

168-
- The purpose of ChatDev is exclusively for research purposes.
169-
- The source code is licensed under Apache 2.0.
170-
- The datasets are licensed under CC BY NC 4.0, which allows for non-commercial use only. It is important to note that
171-
any models trained using these datasets should not be employed for purposes other than research.
174+
- Source Code Licensing: Our project's source code is licensed under the Apache 2.0 License. This license permits the use, modification, and distribution of the code, subject to certain conditions outlined in the Apache 2.0 License.
175+
- Project Open-Source Status: The project is indeed open-source; however, this designation is primarily intended for non-commercial purposes. While we encourage collaboration and contributions from the community for research and non-commercial applications, it is important to note that any utilization of the project's components for commercial purposes necessitates separate licensing agreements.
176+
- Data Licensing: The related data utilized in our project is licensed under CC BY-NC 4.0. This license explicitly permits non-commercial use of the data. We would like to emphasize that any models trained using these datasets should strictly adhere to the non-commercial usage restriction and should be employed exclusively for research purposes.
172177

173178
## Star History
174179

camel/typing.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ class PhaseType(Enum):
6060
RECRUITING_CPO = "recruiting CPO"
6161
RECRUITING_CTO = "recruiting CTO"
6262
DEMAND_ANALYSIS = "demand analysis"
63-
BRAINSTORMING = "brainstorming"
6463
CHOOSING_LANGUAGE = "choosing language"
6564
RECRUITING_PROGRAMMER = "recruiting programmer"
6665
RECRUITING_REVIEWER = "recruiting reviewer"

chatdev/chat_chain.py

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import importlib
22
import json
3+
import logging
34
import os
45
import shutil
5-
from datetime import datetime
6-
import logging
76
import time
7+
from datetime import datetime
88

99
from camel.agents import RolePlaying
1010
from camel.configs import ChatGPTConfig
@@ -63,7 +63,6 @@ def __init__(self,
6363

6464
# init ChatEnv
6565
self.chat_env_config = ChatEnvConfig(clear_structure=check_bool(self.config["clear_structure"]),
66-
brainstorming=check_bool(self.config["brainstorming"]),
6766
gui_design=check_bool(self.config["gui_design"]),
6867
git_management=check_bool(self.config["git_management"]))
6968
self.chat_env = ChatEnv(self.chat_env_config)
@@ -102,8 +101,6 @@ def __init__(self,
102101
log_filepath=self.log_filepath)
103102
self.phases[phase] = phase_instance
104103

105-
106-
107104
def make_recruitment(self):
108105
"""
109106
recruit all employees
@@ -176,7 +173,8 @@ def get_logfilepath(self):
176173
root = os.path.dirname(filepath)
177174
# directory = root + "/WareHouse/"
178175
directory = os.path.join(root, "WareHouse")
179-
log_filepath = os.path.join(directory, "{}.log".format("_".join([self.project_name, self.org_name,start_time])))
176+
log_filepath = os.path.join(directory,
177+
"{}.log".format("_".join([self.project_name, self.org_name, start_time])))
180178
return start_time, log_filepath
181179

182180
def pre_processing(self):
@@ -187,9 +185,7 @@ def pre_processing(self):
187185
"""
188186
if self.chat_env.config.clear_structure:
189187
filepath = os.path.dirname(__file__)
190-
# root = "/".join(filepath.split("/")[:-1])
191188
root = os.path.dirname(filepath)
192-
# directory = root + "/WareHouse"
193189
directory = os.path.join(root, "WareHouse")
194190
for filename in os.listdir(directory):
195191
file_path = os.path.join(directory, filename)
@@ -221,8 +217,8 @@ def pre_processing(self):
221217
preprocess_msg += "**task_prompt**: {}\n\n".format(self.task_prompt_raw)
222218
preprocess_msg += "**project_name**: {}\n\n".format(self.project_name)
223219
preprocess_msg += "**Log File**: {}\n\n".format(self.log_filepath)
224-
preprocess_msg += "**ChatDevConfig**:\n {}\n\n".format(self.chat_env.config.__str__())
225-
preprocess_msg += "**ChatGPTConfig**:\n {}\n\n".format(chat_gpt_config)
220+
preprocess_msg += "**ChatDevConfig**:\n{}\n\n".format(self.chat_env.config.__str__())
221+
preprocess_msg += "**ChatGPTConfig**:\n{}\n\n".format(chat_gpt_config)
226222
log_and_print_online(preprocess_msg)
227223

228224
# init task prompt
@@ -240,9 +236,33 @@ def post_processing(self):
240236

241237
self.chat_env.write_meta()
242238
filepath = os.path.dirname(__file__)
243-
# root = "/".join(filepath.split("/")[:-1])
244239
root = os.path.dirname(filepath)
245240

241+
if self.chat_env_config.git_management:
242+
git_online_log = "**[Git Information]**\n\n"
243+
244+
self.chat_env.codes.version += 1
245+
os.system("cd {}; git add .".format(self.chat_env.env_dict["directory"]))
246+
git_online_log += "cd {}; git add .\n".format(self.chat_env.env_dict["directory"])
247+
os.system("cd {}; git commit -m \"v{} Final Version\"".format(self.chat_env.env_dict["directory"], self.chat_env.codes.version))
248+
git_online_log += "cd {}; git commit -m \"v{} Final Version\"\n".format(self.chat_env.env_dict["directory"], self.chat_env.codes.version)
249+
log_and_print_online(git_online_log)
250+
251+
git_info = "**[Git Log]**\n\n"
252+
import subprocess
253+
254+
# 执行git log命令
255+
command = "cd {}; git log".format(self.chat_env.env_dict["directory"])
256+
completed_process = subprocess.run(command, shell=True, text=True, stdout=subprocess.PIPE)
257+
258+
if completed_process.returncode == 0:
259+
log_output = completed_process.stdout
260+
else:
261+
log_output = "Error when executing " + command
262+
263+
git_info += log_output
264+
log_and_print_online(git_info)
265+
246266
post_info = "**[Post Info]**\n\n"
247267
now_time = now()
248268
time_format = "%Y%m%d%H%M%S"
@@ -251,7 +271,8 @@ def post_processing(self):
251271
duration = (datetime2 - datetime1).total_seconds()
252272

253273
post_info += "Software Info: {}".format(
254-
get_info(self.chat_env.env_dict['directory'], self.log_filepath) + "\n\n🕑**duration**={:.2f}s\n\n".format(duration))
274+
get_info(self.chat_env.env_dict['directory'], self.log_filepath) + "\n\n🕑**duration**={:.2f}s\n\n".format(
275+
duration))
255276

256277
post_info += "ChatDev Starts ({})".format(self.start_time) + "\n\n"
257278
post_info += "ChatDev Ends ({})".format(now_time) + "\n\n"

chatdev/chat_env.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,17 @@
1717

1818
class ChatEnvConfig:
1919
def __init__(self, clear_structure,
20-
brainstorming,
2120
gui_design,
2221
git_management):
2322
self.clear_structure = clear_structure
24-
self.brainstorming = brainstorming
2523
self.gui_design = gui_design
2624
self.git_management = git_management
2725

2826
def __str__(self):
2927
string = ""
3028
string += "ChatEnvConfig.clear_structure: {}\n".format(self.clear_structure)
31-
string += "ChatEnvConfig.brainstorming: {}\n".format(self.brainstorming)
29+
string += "ChatEnvConfig.git_management: {}\n".format(self.git_management)
30+
string += "ChatEnvConfig.gui_design: {}\n".format(self.gui_design)
3231
return string
3332

3433

@@ -112,7 +111,7 @@ def exist_bugs(self) -> tuple[bool, str]:
112111
else:
113112
os.kill(process.pid, signal.SIGTERM)
114113
if process.poll() is None:
115-
os.kill(process.pid,signal.CTRL_BREAK_EVENT)
114+
os.kill(process.pid, signal.CTRL_BREAK_EVENT)
116115

117116
if return_code == 0:
118117
return False, success_info
@@ -143,8 +142,8 @@ def print_employees(self):
143142
def update_codes(self, generated_content):
144143
self.codes._update_codes(generated_content)
145144

146-
def rewrite_codes(self) -> None:
147-
self.codes._rewrite_codes(self.config.git_management)
145+
def rewrite_codes(self, phase_info=None) -> None:
146+
self.codes._rewrite_codes(self.config.git_management, phase_info)
148147

149148
def get_codes(self) -> str:
150149
return self.codes._get_codes()

chatdev/codes.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1+
import difflib
12
import os
23
import re
4+
import subprocess
35

46
from chatdev.utils import log_and_print_online
5-
import difflib
7+
68

79
class Codes:
810
def __init__(self, generated_content=""):
911
self.directory: str = None
10-
self.version: float = 1.0
12+
self.version: float = 0.0
1113
self.generated_content: str = generated_content
1214
self.codebooks = {}
1315

@@ -71,7 +73,7 @@ def _update_codes(self, generated_content):
7173
log_and_print_online(update_codes_content)
7274
self.codebooks[key] = new_codes.codebooks[key]
7375

74-
def _rewrite_codes(self, git_management) -> None:
76+
def _rewrite_codes(self, git_management, phase_info=None) -> None:
7577
directory = self.directory
7678
rewrite_codes_content = "**[Rewrite Codes]**\n\n"
7779
if os.path.exists(directory) and len(os.listdir(directory)) > 0:
@@ -87,12 +89,35 @@ def _rewrite_codes(self, git_management) -> None:
8789
rewrite_codes_content += os.path.join(directory, filename) + " Wrote\n"
8890

8991
if git_management:
92+
if not phase_info:
93+
phase_info = ""
94+
git_online_log = "**[Git Information]**\n\n"
9095
if self.version == 1.0:
9196
os.system("cd {}; git init".format(self.directory))
97+
git_online_log += "cd {}; git init\n".format(self.directory)
9298
os.system("cd {}; git add .".format(self.directory))
93-
os.system("cd {}; git commit -m \"{}\"".format(self.directory, self.version))
94-
95-
log_and_print_online(rewrite_codes_content)
99+
git_online_log += "cd {}; git add .\n".format(self.directory)
100+
101+
# check if there exist diff
102+
completed_process = subprocess.run("cd {}; git status".format(self.directory), shell=True, text=True,
103+
stdout=subprocess.PIPE)
104+
if "nothing to commit" in completed_process.stdout:
105+
self.version -= 1.0
106+
return
107+
108+
os.system("cd {}; git commit -m \"v{}\"".format(self.directory, str(self.version) + " " + phase_info))
109+
git_online_log += "cd {}; git commit -m \"v{}\"\n".format(self.directory,
110+
str(self.version) + " " + phase_info)
111+
if self.version == 1.0:
112+
os.system("cd {}; git submodule add ./{} {}".format(os.path.dirname(os.path.dirname(self.directory)),
113+
"WareHouse/" + os.path.basename(self.directory),
114+
"WareHouse/" + os.path.basename(self.directory)))
115+
git_online_log += "cd {}; git submodule add ./{} {}\n".format(
116+
os.path.dirname(os.path.dirname(self.directory)),
117+
"WareHouse/" + os.path.basename(self.directory),
118+
"WareHouse/" + os.path.basename(self.directory))
119+
log_and_print_online(rewrite_codes_content)
120+
log_and_print_online(git_online_log)
96121

97122
def _get_codes(self) -> str:
98123
content = ""

chatdev/composed_phase.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def execute(self, chat_env) -> ChatEnv:
135135
136136
"""
137137
self.update_phase_env(chat_env)
138-
for cycle_index in range(self.cycle_num):
138+
for cycle_index in range(1, self.cycle_num + 1):
139139
for phase_item in self.composition:
140140
assert phase_item["phaseType"] == "SimplePhase" # right now we do not support nested composition
141141
phase = phase_item['phase']

chatdev/phase.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,6 @@ def self_reflection(self,
207207
question = """Answer their final discussed conclusion (Yes or No) in the discussion without any other words, e.g., "Yes" """
208208
elif phase_name == "DemandAnalysis":
209209
question = """Answer their final product modality in the discussion without any other words, e.g., "PowerPoint" """
210-
# elif phase_name in [PhaseType.BRAINSTORMING]:
211-
# question = """Conclude three most creative and imaginative brainstorm ideas from the whole discussion, in the format: "1) *; 2) *; 3) *; where '*' represents a suggestion." """
212210
elif phase_name == "LanguageChoose":
213211
question = """Conclude the programming language being discussed for software development, in the format: "*" where '*' represents a programming language." """
214212
elif phase_name == "EnvironmentDoc":
@@ -356,7 +354,7 @@ def update_chat_env(self, chat_env) -> ChatEnv:
356354
chat_env.update_codes(self.seminar_conclusion)
357355
if len(chat_env.codes.codebooks.keys()) == 0:
358356
raise ValueError("No Valid Codes.")
359-
chat_env.rewrite_codes()
357+
chat_env.rewrite_codes("Finish Coding")
360358
log_and_print_online(
361359
"**[Software Info]**:\n\n {}".format(get_info(chat_env.env_dict['directory'], self.log_filepath)))
362360
return chat_env
@@ -392,7 +390,7 @@ def update_phase_env(self, chat_env):
392390

393391
def update_chat_env(self, chat_env) -> ChatEnv:
394392
chat_env.update_codes(self.seminar_conclusion)
395-
chat_env.rewrite_codes()
393+
chat_env.rewrite_codes("Finish Art Integration")
396394
# chat_env.generate_images_from_codes()
397395
log_and_print_online(
398396
"**[Software Info]**:\n\n {}".format(get_info(chat_env.env_dict['directory'], self.log_filepath)))
@@ -424,7 +422,7 @@ def update_chat_env(self, chat_env) -> ChatEnv:
424422
chat_env.update_codes(self.seminar_conclusion)
425423
if len(chat_env.codes.codebooks.keys()) == 0:
426424
raise ValueError("No Valid Codes.")
427-
chat_env.rewrite_codes()
425+
chat_env.rewrite_codes("Code Complete #" + str(self.phase_env["cycle_index"]) + " Finished")
428426
log_and_print_online(
429427
"**[Software Info]**:\n\n {}".format(get_info(chat_env.env_dict['directory'], self.log_filepath)))
430428
return chat_env
@@ -463,7 +461,7 @@ def update_phase_env(self, chat_env):
463461
def update_chat_env(self, chat_env) -> ChatEnv:
464462
if "```".lower() in self.seminar_conclusion.lower():
465463
chat_env.update_codes(self.seminar_conclusion)
466-
chat_env.rewrite_codes()
464+
chat_env.rewrite_codes("Review #" + str(self.phase_env["cycle_index"]) + " Finished")
467465
log_and_print_online(
468466
"**[Software Info]**:\n\n {}".format(get_info(chat_env.env_dict['directory'], self.log_filepath)))
469467
self.phase_env['modification_conclusion'] = self.seminar_conclusion
@@ -484,7 +482,7 @@ def update_phase_env(self, chat_env):
484482
def update_chat_env(self, chat_env) -> ChatEnv:
485483
if "```".lower() in self.seminar_conclusion.lower():
486484
chat_env.update_codes(self.seminar_conclusion)
487-
chat_env.rewrite_codes()
485+
chat_env.rewrite_codes("Human Review #" + str(self.phase_env["cycle_index"]) + " Finished")
488486
log_and_print_online(
489487
"**[Software Info]**:\n\n {}".format(get_info(chat_env.env_dict['directory'], self.log_filepath)))
490488
return chat_env
@@ -496,14 +494,14 @@ def execute(self, chat_env, chat_turn_limit, need_reflect) -> ChatEnv:
496494
f"Now you can participate in the development of the software!\n"
497495
f"The task is: {chat_env.env_dict['task_prompt']}\n"
498496
f"Please input your feedback (in one line). It can be bug report or new feature requirement.\n"
499-
f"You are currently in the #{self.phase_env['cycle_index'] + 1} human feedback with a total of {self.phase_env['cycle_num']} feedbacks\n"
497+
f"You are currently in the #{self.phase_env['cycle_index']} human feedback with a total of {self.phase_env['cycle_num']} feedbacks\n"
500498
f"Press [Enter] to submit.\n"
501499
f"You can type \"End\" to quit this mode at any time.\n"
502500
)
503501
provided_comments = input(">>> ")
504502
self.phase_env["comments"] = provided_comments
505503
log_and_print_online(
506-
f"**[User Provided Comments]**\n\n In the #{self.phase_env['cycle_index'] + 1} of total {self.phase_env['cycle_num']} comments: \n\n" + provided_comments)
504+
f"**[User Provided Comments]**\n\n In the #{self.phase_env['cycle_index']} of total {self.phase_env['cycle_num']} comments: \n\n" + provided_comments)
507505
if provided_comments.lower() == "end":
508506
return chat_env
509507

@@ -592,7 +590,7 @@ def update_phase_env(self, chat_env):
592590
def update_chat_env(self, chat_env) -> ChatEnv:
593591
if "```".lower() in self.seminar_conclusion.lower():
594592
chat_env.update_codes(self.seminar_conclusion)
595-
chat_env.rewrite_codes()
593+
chat_env.rewrite_codes("Test #" + str(self.phase_env["cycle_index"]) + " Finished")
596594
log_and_print_online(
597595
"**[Software Info]**:\n\n {}".format(get_info(chat_env.env_dict['directory'], self.log_filepath)))
598596
return chat_env

misc/github.png

65.9 KB
Loading

0 commit comments

Comments
 (0)