as-cle-bert commited on
Commit
59d87f3
1 Parent(s): 39652f5

Create main.py

Browse files
Files changed (1) hide show
  1. main.py +184 -0
main.py ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_openai import ChatOpenAI
2
+ from langchain_core.prompts import ChatPromptTemplate
3
+ import os
4
+ from langchain_core.pydantic_v1 import BaseModel, Field
5
+ import gradio as gr
6
+
7
+
8
+ class code(BaseModel):
9
+ """Code output"""
10
+
11
+ prefix: str = Field(description="Description of the problem and approach")
12
+ imports: str = Field(description="Code block import statements")
13
+ code: str = Field(description="Code block not including import statements")
14
+ possible_errors: str = Field(description="Description of potential error and vulnerabilities in the code")
15
+ description = "Schema for code solutions to questions about Code."
16
+
17
+ class revision(BaseModel):
18
+ """Revision output"""
19
+
20
+ imports_revision: str = Field(description="Revision of imports")
21
+ code_revision: str = Field(description="Revision of code")
22
+ overall_evaluation: str = Field(description="Thorough evaluation of the imports and of the code")
23
+ description = "Schema for code solutions to questions about Code."
24
+
25
+ def dict_to_string(d):
26
+ # Create a list of strings in the form '-key value'
27
+ parts = [f"{key}:\n\t{value}" for key, value in d.items()]
28
+ # Join the parts with a space separator
29
+ result = '\n'.join(parts)
30
+ return result
31
+
32
+ def coder_reply_to_string(solution: code):
33
+ d = solution.__dict__
34
+ return dict_to_string(d)
35
+
36
+ class CodeGenerator:
37
+ def __init__(self, coder, revisor, maxiters):
38
+ self.coder = coder
39
+ self.revisor = revisor
40
+ self.maxiters = maxiters
41
+ def generate(self, prompt, context):
42
+ i = 0
43
+ while i < self.maxiters:
44
+ solution = self.coder.invoke({"context": context, "messages": [("user", prompt)]})
45
+ revision = self.revisor.invoke({"messages": [("user", coder_reply_to_string(solution))]})
46
+ context = coder_reply_to_string(revision)
47
+ i+=1
48
+ return solution
49
+
50
+ class modularized_code(BaseModel):
51
+ prefix: str = Field(description="Description of the problem and approach")
52
+ imports: str = Field(description="Code block import statements")
53
+ code: str = Field(description="Modularized code block not including import statements")
54
+ description = "Schema for code solutions to questions about Code."
55
+
56
+ def check_code(solution):
57
+ try:
58
+ exec(solution.imports)
59
+ except Exception as e:
60
+ return f"An error occurred during import phase: {e}"
61
+ try:
62
+ exec(solution.imports+"\n"+solution.code)
63
+ return "Code ran succesfully"
64
+ except Exception as e:
65
+ return f"An error occurred during code execution phase: {e}"
66
+
67
+ class CodeChecker:
68
+ def __init__(self, solution, checker):
69
+ self.solution = solution
70
+ self.checker = checker
71
+ def check_n_refactor(self, iterations):
72
+ for i in range(iterations):
73
+ try:
74
+ success_status = check_code(self.solution)
75
+ except Exception as e:
76
+ success_status = f"An error occurred while checking the code: {e}"
77
+ print("Success status: " + success_status)
78
+ if success_status == "Code run succesfully":
79
+ return self.solution
80
+ else:
81
+ self.solution = self.checker.invoke({"code": self.solution.imports + "\n" + self.solution.code, "errors": success_status})
82
+ return self.solution
83
+
84
+ # Grader prompt
85
+ code_gen_prompt = ChatPromptTemplate.from_messages(
86
+ [
87
+ (
88
+ "system",
89
+ """You are a coding assistant with expertise in python. Based on the following context (which can be code or revision suggestions): \n ------- \n {context} \n ------- \n Answer the user
90
+ question. Ensure any code you provide can be executed \n
91
+ with all required imports and variables defined. First, structure your answer with a description of the code solution. \n
92
+ Secondly list the imports. Thirdly list the functioning code block. Finally, describe potential errors one might encounter while executing the code. Here is the user question:""",
93
+ ),
94
+ ("placeholder", "{messages}"),
95
+ ]
96
+ )
97
+
98
+ revisor_prompt = ChatPromptTemplate.from_messages(
99
+ [
100
+ (
101
+ "system",
102
+ """You are a coding revisor with expertise in python. From the prefix, import, code and potential errors produced by a programmer, you should provide a thorough review with:
103
+ - First what would you improve in the imports
104
+ - Second what would you improve in the code block
105
+ - Third an overall evaluation of the whole code solution produced by the programmer. Here is the programmer solution you should revise:""",
106
+ ),
107
+ ("placeholder", "{messages}"),
108
+ ]
109
+ )
110
+
111
+ modules_prompt = ChatPromptTemplate.from_messages(
112
+ [
113
+ (
114
+ "system",
115
+ """Your job is to refactor code in a modularized way, and you have expertise in python. From the prefix, import, code and potential errors produced by a programmer, you should provide a refactored and modularized code with:
116
+ - A description of what you did
117
+ - The imports
118
+ - The refactored and modularized code.
119
+ Orient code generation on this context (which may be user's request or some revision suggestions):
120
+ \n\n-----------\n{context}\n-------------\n\n
121
+ Here is the programmer solution you should refactor and modularize:""",
122
+ ),
123
+ ("placeholder", "{messages}"),
124
+ ]
125
+ )
126
+
127
+ checker_prompt = ChatPromptTemplate.from_messages(
128
+ [
129
+ (
130
+ "system",
131
+ """Your job is to refactor code based on these errors:
132
+
133
+ ----------
134
+ {errors}
135
+ ----------
136
+
137
+ This is the code to refactor:
138
+
139
+ ----------
140
+ {code}
141
+ ----------
142
+ You should then reply with:
143
+ - A description of what you did
144
+ - The imports
145
+ - The refactored code""",
146
+ ),
147
+ ]
148
+ )
149
+
150
+ import time
151
+
152
+ def reply(message, history, api_key, context):
153
+ os.environ["OPENAI_API_KEY"] = api_key
154
+ expt_llm = "gpt-4o"
155
+ llm = ChatOpenAI(temperature=0, model=expt_llm)
156
+ code_gen_chain = code_gen_prompt | llm.with_structured_output(code)
157
+ code_revision_chain = revisor_prompt | llm.with_structured_output(revision)
158
+ aicodegenerator = CodeGenerator(code_gen_chain, code_revision_chain, 5)
159
+ solution = aicodegenerator.generate(prompt=message, context=context)
160
+ code_modules_chain = modules_prompt | llm.with_structured_output(modularized_code)
161
+ aicodemodularizer = CodeGenerator(code_modules_chain, code_revision_chain, 5)
162
+ modules_solution = aicodemodularizer.generate(prompt=coder_reply_to_string(solution), context=message)
163
+ code_checker_chain = checker_prompt | llm.with_structured_output(code)
164
+ aicodechecker = CodeChecker(modules_solution, code_checker_chain)
165
+ final_solution = aicodechecker.check_n_refactor(5)
166
+ response = "The final solution for your code is:\n\n```python" + final_solution.imports + "\n" + final_solution.code + "\n```"
167
+ this_hist = ""
168
+ for char in response:
169
+ this_hist+=char
170
+ time.sleep(0.001)
171
+ yield this_hist
172
+
173
+ api_key_user = gr.Textbox(label="OpenAI API key", type="password")
174
+ context_user = gr.Textbox(label="Context", info="Add some contextual instructions for the model to know how to generate code", value="def hello_world():\n\tprint('Hello world!')\n\nhello_world()")
175
+
176
+ chatbot = gr.Chatbot(height=400)
177
+ additional_accordion = gr.Accordion(label="Parameters to be set before you start chatting", open=True)
178
+
179
+ with gr.Blocks() as demo:
180
+ gr.HTML("<h1 align='center'>Self-Reviewing Coding Assistant🤖💻</h1>")
181
+ gr.Image('coding_assistant.png')
182
+ gr.ChatInterface(fn=reply, additional_inputs=[api_key_user, context_user], additional_inputs_accordion=additional_accordion, chatbot=chatbot)
183
+
184
+ demo.launch(server_name="0.0.0.0", server_port=7860)