Mahinour1 commited on
Commit
716d5ad
·
1 Parent(s): 45adabc

midterm changes

Browse files
Dockerfile CHANGED
@@ -93,4 +93,4 @@ RUN uv sync
93
  EXPOSE 7860
94
 
95
  # Run the app
96
- CMD ["uv", "run", "chainlit", "run", "app.py", "--host", "0.0.0.0", "--port", "7860"]
 
93
  EXPOSE 7860
94
 
95
  # Run the app
96
+ CMD ["uv", "run", "chainlit", "run", "app_2.py", "--host", "0.0.0.0", "--port", "7860"]
app_2.py ADDED
@@ -0,0 +1,393 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import getpass
3
+ from operator import itemgetter
4
+ from typing import List, Dict
5
+ import json
6
+ import requests
7
+ import traceback
8
+
9
+
10
+
11
+ #LangChain, LangGraph
12
+ from langchain_openai import ChatOpenAI
13
+ from langgraph.graph import START, StateGraph, END
14
+ from typing_extensions import List, TypedDict
15
+ # from langchain_core.documents import Document
16
+ from langchain_core.prompts import ChatPromptTemplate
17
+ from langchain.schema.output_parser import StrOutputParser
18
+ from langchain_core.tools import Tool, tool
19
+ from langgraph.prebuilt import ToolNode
20
+ from typing import TypedDict, Annotated
21
+ from langgraph.graph.message import add_messages
22
+ import operator
23
+ from langchain_core.messages import BaseMessage, HumanMessage, AIMessage, SystemMessage
24
+ from langchain.vectorstores import Qdrant
25
+ from langchain.embeddings import OpenAIEmbeddings
26
+ from langchain.schema import Document
27
+ from qdrant_client import QdrantClient
28
+ from qdrant_client.http.models import Distance, VectorParams
29
+
30
+
31
+ import chainlit as cl
32
+ import tempfile
33
+ import shutil
34
+
35
+ #helper imports
36
+ from code_analysis import *
37
+ from tools import search_pypi, write_to_docx
38
+ from prompts import main_prompt, documenter_prompt, code_description_prompt
39
+ from states import AgentState
40
+
41
+
42
+ # read openai key
43
+ os.environ["OPENAI_API_KEY"] = "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"
44
+
45
+ # Global variables to store processed data
46
+ processed_file_path = None
47
+ document_file_path = None
48
+ vectorstore = None
49
+ main_chain = None
50
+ qdrant_client = None
51
+
52
+ @cl.on_chat_start
53
+ async def on_chat_start():
54
+ await cl.Message(content="Welcome to the Python Code Documentation Assistant! Please upload a Python file to get started.").send()
55
+
56
+ @cl.on_message
57
+ async def on_message(message: cl.Message):
58
+ global processed_file_path, document_file_path, vectorstore, main_chain, qdrant_client
59
+
60
+ if message.elements and any(el.type == "file" for el in message.elements):
61
+ file_elements = [el for el in message.elements if el.type == "file"]
62
+ file_element = file_elements[0]
63
+ is_python_file = (
64
+ file_element.mime.startswith("text/x-python") or
65
+ file_element.name.endswith(".py") or
66
+ file_element.mime == "text/plain" # Some systems identify .py as text/plain
67
+ )
68
+ if is_python_file:
69
+ # Send processing message
70
+ msg = cl.Message(content="Processing your Python file...")
71
+ await msg.send()
72
+
73
+ print(f'file element \n {file_element} \n')
74
+
75
+ # Save uploaded file to a temporary location
76
+ temp_dir = tempfile.mkdtemp()
77
+ file_path = os.path.join(temp_dir, file_element.name)
78
+
79
+ with open(file_element.path, "rb") as source_file:
80
+ file_content_bytes = source_file.read()
81
+ with open(file_path, "wb") as destination_file:
82
+ destination_file.write(file_content_bytes)
83
+
84
+ processed_file_path = file_path
85
+
86
+ try:
87
+
88
+ # read file and extract imports
89
+ file_content = read_python_file(file_path)
90
+ # imports = extract_imports(file_content, file_path)
91
+
92
+ print(f'Done reading file')
93
+
94
+ # Define describe packages graph
95
+ search_packages_tools = [search_pypi]
96
+ ##################################### DESCRIBE CODE AGENT ####################################
97
+ describe_code_llm = ChatOpenAI(model="gpt-4o-mini")
98
+ # describe_imports_llm = describe_imports_llm.bind_tools(tools = search_packages_tools, tool_choice="required")
99
+
100
+ describe_code_prompt = ChatPromptTemplate.from_messages([
101
+ ("system", code_description_prompt),
102
+ ("human", "{code}")
103
+ ])
104
+
105
+ describe_code_chain = (
106
+ {"code_language": itemgetter("code_language"), "code": itemgetter("code")}
107
+ | describe_code_prompt | describe_code_llm | StrOutputParser()
108
+ )
109
+
110
+ print(f'done defining imports chain')
111
+
112
+
113
+ # Define describe code chain node
114
+ def describe_code(state):
115
+ # print("Starting chain function")
116
+ last_message= state["messages"][-1]
117
+ # print(f'last message is \n {last_message}')
118
+ content = json.loads(last_message.content)
119
+ # print(f'content is {content}')
120
+ # print(type(content))
121
+ chain_input = {"code_language": content['code_language'],
122
+ "code": content['code']}
123
+ # print(f'chain_input is {chain_input}')
124
+ # print(type(chain_input))
125
+ response = describe_code_chain.invoke(chain_input)
126
+ # print(f"Chain response: {response}")
127
+ return {"messages": [AIMessage(content=response)]}
128
+
129
+ ######################################## DOCUMENT WRITER AGENT ###################################3
130
+ documenter_llm = ChatOpenAI(model="gpt-4o-mini")
131
+
132
+ documenter_llm_prompt = ChatPromptTemplate.from_messages([
133
+ ("system", documenter_prompt),
134
+ ("human", "{content}")
135
+ ])
136
+
137
+ documenter_chain = (
138
+ {"content": itemgetter("content")}
139
+ | documenter_llm_prompt
140
+ | documenter_llm
141
+ | StrOutputParser()
142
+ )
143
+
144
+ def write_document_content(state):
145
+ print(state)
146
+ json_content = state['messages'][-1].content
147
+ json_content = json_content[json_content.find("{"):json_content.rfind("}")+1].strip()
148
+ json_content = json.loads(json_content)
149
+ document_response = documenter_chain.invoke({"content": json_content})
150
+ return {"messages": [AIMessage(content=document_response)]}
151
+
152
+ ########################################## CONSTRUCT GRAPH ############################################################33
153
+ class AgentState(TypedDict):
154
+ messages: Annotated[list, add_messages]
155
+
156
+ uncompiled_code_graph = StateGraph(AgentState)
157
+ uncompiled_code_graph.add_node("code_agent", describe_code)
158
+ uncompiled_code_graph.add_node("write_content_agent", write_document_content)
159
+ uncompiled_code_graph.add_node("write_document", write_to_docx)
160
+
161
+ uncompiled_code_graph.set_entry_point("code_agent")
162
+ uncompiled_code_graph.add_edge("code_agent", "write_content_agent")
163
+ uncompiled_code_graph.add_edge("write_content_agent", "write_document")
164
+
165
+ compiled_code_graph = uncompiled_code_graph.compile()
166
+
167
+
168
+ initial_state = {
169
+ "messages": [{
170
+ "role": "human",
171
+ "content": json.dumps({
172
+ "code_language": "python",
173
+ "code": file_content
174
+ })
175
+ }]
176
+ }
177
+ # bind model to tool or ToolNode
178
+ # imports_tool_node = ToolNode(search_packages_tools)
179
+
180
+ # construct graph and compile
181
+ # uncompiled_imports_graph = StateGraph(AgentState)
182
+ # uncompiled_imports_graph.add_node("imports_agent", call_imports_chain)
183
+ # uncompiled_imports_graph.add_node("imports_action", imports_tool_node)
184
+ # uncompiled_imports_graph.set_entry_point("imports_agent")
185
+
186
+ # def should_continue(state):
187
+ # last_message = state["messages"][-1]
188
+
189
+ # if last_message.tool_calls:
190
+ # return "imports_action"
191
+
192
+ # return END
193
+
194
+ # uncompiled_imports_graph.add_conditional_edges(
195
+ # "imports_agent",
196
+ # should_continue
197
+ # )
198
+
199
+ # uncompiled_imports_graph.add_edge("imports_action", "imports_agent")
200
+
201
+ # compiled_imports_graph = uncompiled_imports_graph.compile()
202
+
203
+ # print(f'compiled imports graph')
204
+ # # Invoke imports graph
205
+ # initial_state = {
206
+ # "messages": [{
207
+ # "role": "human",
208
+ # "content": json.dumps({
209
+ # "code_language": "python",
210
+ # "imports": imports
211
+ # })
212
+ # }]
213
+ # }
214
+
215
+
216
+
217
+
218
+
219
+ # await msg.update(content="Analyzing imports and generating documentation...")
220
+ msg.content = "Analyzing your code and generating documentation..."
221
+ await msg.update()
222
+
223
+ # msg = cl.Message(content="Analyzing your code and generating documentation...")
224
+ # await msg.send()
225
+
226
+ documenter_result = compiled_code_graph.invoke(initial_state)
227
+
228
+ ############################################## SAVE DESCRIPTION CHUNKS IN VECTOR STORE ########################################3
229
+ qdrant_client = QdrantClient(":memory:")
230
+
231
+ embedding_model = OpenAIEmbeddings(model="text-embedding-3-small")
232
+ embedding_dim = 1536
233
+
234
+ qdrant_client.create_collection(
235
+ collection_name="description_rag_data",
236
+ vectors_config=VectorParams(size=embedding_dim, distance=Distance.COSINE),
237
+ )
238
+
239
+ vectorstore = Qdrant(qdrant_client, collection_name="description_rag_data", embeddings=embedding_model)
240
+
241
+ # Add chunks
242
+ chunks = documenter_result['messages'][1].content
243
+ chunks = chunks[chunks.find("{"):chunks.rfind("}")+1].strip()
244
+ chunks = json.loads(chunks)
245
+ print(f'################################### raw chunks \n {chunks} \n ######################## \n')
246
+ chunks_list = []
247
+ for key in chunks:
248
+ if isinstance(chunks[key], dict):
249
+ chunks_list.append(chunks[key])
250
+ elif isinstance(chunks[key], list):
251
+ for value in chunks[key]:
252
+ chunks_list.append(value)
253
+ print(f'################################### chunks_list \n {chunks_list} \n ######################## \n')
254
+ docs = [
255
+ Document(
256
+ page_content=f"{chunk.get('type', '')} - {chunk.get('name', '')} - {chunk.get('description', '')}", # Content for the model
257
+ metadata={**chunk} # Store metadata, but don't put embeddings here
258
+ )
259
+ for chunk in chunks_list
260
+ ]
261
+
262
+
263
+
264
+ vectorstore.add_documents(docs)
265
+ qdrant_retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
266
+
267
+ print('done adding docs to DB')
268
+ #define documenter chain
269
+ # documenter_llm = ChatOpenAI(model="gpt-4o-mini")
270
+ # documenter_llm_prompt = ChatPromptTemplate.from_messages([
271
+ # ("system", documenter_prompt),
272
+ # ])
273
+ # documenter_chain = (
274
+ # {"context": itemgetter("context")}
275
+ # | documenter_llm_prompt
276
+ # | documenter_llm
277
+ # | StrOutputParser()
278
+ # )
279
+
280
+ # print('done defining documenter chain')
281
+
282
+ #extract description chunks from database
283
+ # collection_name = "description_rag_data"
284
+ # all_points = qdrant_client.scroll(collection_name=collection_name, limit=1000)[0] # Adjust limit if needed
285
+ # one_chunk = all_points[0].payload
286
+ # input_text = f"type: {one_chunk['metadata']['type']} \nname: {one_chunk['metadata']['name']} \ncontent: {one_chunk['metadata']['content']}"
287
+
288
+ # print('done extracting chunks form DB')
289
+
290
+ # document_response = documenter_chain.invoke({"context": input_text})
291
+
292
+ print('done invoking documenter chain and will write in docx')
293
+ # write packages description in word file
294
+ # document_file_path = write_to_docx(document_response)
295
+ # print (f'################################ \n documenter_result \n {documenter_result} \n ############################ \n')
296
+ # document_file_path = documenter_result['messages'][-1].content[0]
297
+ # print()
298
+ document_file_path = 'generated_documentation.docx'
299
+
300
+
301
+ print('done writing docx file')
302
+ # Set up Main Chain for chat
303
+ main_llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
304
+
305
+
306
+ main_llm_prompt = ChatPromptTemplate.from_messages([
307
+ ("system", main_prompt),
308
+ ("human", "{query}")
309
+ ])
310
+
311
+ main_chain = (
312
+ {"context": itemgetter("query") | qdrant_retriever, "code_language": itemgetter("code_language"), "query": itemgetter("query"), }
313
+ | main_llm_prompt
314
+ | main_llm
315
+ | StrOutputParser()
316
+ )
317
+
318
+ print('done defining main chain')
319
+ # Present download button for the document
320
+ elements = [
321
+ cl.File(
322
+ name="documentation.docx",
323
+ path=document_file_path,
324
+ display="inline"
325
+ )
326
+ ]
327
+ print('done defining elements')
328
+ msg.content = "✅ Your Python file has been processed! You can download the documentation file below. How can I help you with your code?"
329
+ msg.elements = elements
330
+ await msg.update()
331
+
332
+ # await msg.update(
333
+ # content="✅ Your Python file has been processed! You can download the documentation file below. How can I help you with your code?.",
334
+ # elements=elements
335
+ # )
336
+
337
+ except Exception as e:
338
+ # await msg.update(content=f"❌ Error processing file: {str(e)}")
339
+ error_traceback = traceback.format_exc()
340
+ print(error_traceback)
341
+ msg.content = f"❌ Error processing file: {str(e)}"
342
+ await msg.update()
343
+
344
+ # msg = cl.Message(content=f"second message ❌ Error processing file: {str(e)}")
345
+ # await msg.send()
346
+
347
+ else:
348
+ await cl.Message(content="Please upload a Python (.py) file.").send()
349
+
350
+ # Handle chat messages if file has been processed
351
+ elif processed_file_path and main_chain:
352
+ user_input = message.content
353
+ # Send thinking message
354
+ msg = cl.Message(content="Thinking...")
355
+ await msg.send()
356
+
357
+ try:
358
+ # Use main_chain to answer the query
359
+ # invoke main chain
360
+ inputs = {
361
+ 'code_language': 'Python',
362
+ 'query': user_input
363
+ }
364
+
365
+ response = main_chain.invoke(inputs)
366
+
367
+ # Update with the response
368
+ # await msg.update(content=response)
369
+ msg.content = response
370
+ await msg.update()
371
+
372
+ # msg = cl.Message(content=response)
373
+ # await msg.send()
374
+
375
+ except Exception as e:
376
+ # await msg.update(content=f"❌ Error processing your question: {str(e)}")
377
+ msg.content = f"❌ Error processing your question: {str(e)}"
378
+ await msg.update()
379
+
380
+ # msg = cl.Message(content=f"❌ Error processing your question: {str(e)}")
381
+ # await msg.send()
382
+
383
+ else:
384
+ await cl.Message(content="Please upload a Python file first before asking questions.").send()
385
+
386
+
387
+ @cl.on_stop
388
+ def on_stop():
389
+ global processed_file_path
390
+ # Clean up temporary files
391
+ if processed_file_path and os.path.exists(os.path.dirname(processed_file_path)):
392
+ shutil.rmtree(os.path.dirname(processed_file_path))
393
+
app_2.py:Zone.Identifier ADDED
File without changes
prompts.py CHANGED
@@ -1,49 +1,169 @@
1
- describe_imports = """You are an expert {code_language} developer.
2
- Your will be given code lines that import packages.
3
- Your role is to give a brief description of each package
4
-
5
- You have access to the following tool and you MUST use it:
6
- search_pypi: Use this to get information about Python packages from PyPI.
7
-
8
- For each import:
9
- 1. Extract the main package name
10
- 2. Use the search_pypi tool to get package information by calling "search_pypi(package_name)"
11
- 3. Combine the information into a clear description
12
- 4. If the retuned value of tool is empty use your own knowledge
13
- 5. If you have no knowledge for this package then it's description should be "I don't know details about this package"
14
-
15
- You must respond in the following JSON format:
16
- {{"Imported_Packages": [
17
- {{"name": "package1", "desc": "brief description of package1"}},
18
- {{"name": "package2", "desc": "brief description of package2"}}
19
- ]}}
20
 
21
- Rules for the output:
22
- 1. Use valid JSON format
23
- 2. Package names should be the exact names from the imports
24
- 3. Descriptions should be brief and clear
25
- 4. Do not include any text outside the JSON structure
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  """
27
 
28
- documenter_prompt = """You are an expert code documenter.
29
- Your role is to write a well structured document that describes code functionality.
 
30
 
31
- From the given context:
32
- 1- type: is the type of the code block (funciton, class, ..)
33
- 2- name: is the name of the code block
34
- 3- content: is the description of the code block
35
 
36
- Instructions:
37
- Write a docx document with the following structure Heading 1(type) -> Heading 2(name) -> content
 
 
 
 
38
 
39
- Rules for the output:
40
- 1. Don't write information out of context
41
- 2. If needed, structure long responses in lists and sections
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
- <context>
44
- {context}
45
- </context>
46
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
  main_prompt = """You are an expert {code_language} developer.
49
  Your role is to answer user's questions about code and its description that will be given to you in context.
 
1
+ code_description_prompt = """
2
+ You are an expert {code_language} developer.
3
+ Your will be given python code lines.
4
+ Your role is to break down its components into a specific JSON format.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
+ Input:
7
+ A Python file containing:
8
+ 1- Imports
9
+ 2- Function definitions
10
+ 3- Execution code
11
+
12
+ Output Format:
13
+ The output should be a JSON with three main sections:
14
+ 1- Imports
15
+ {{
16
+ "type": "imports",
17
+ "description": [
18
+ {{"package1_name": "detailed description of package1"}},
19
+ {{"package2_name": "detailed description of package2"}}
20
+ ]
21
+ }}
22
+
23
+ 2- Functions
24
+ {{
25
+ "functions": [
26
+ {{
27
+ "type": "function",
28
+ "name": "function1_name",
29
+ "description": "detailed explanation of function1's purpose and functionality"
30
+ }},
31
+ {{
32
+ "type": "function",
33
+ "name": "function2_name",
34
+ "description": "detailed explanation of function2's purpose and functionality"
35
+ }}
36
+ ]
37
+ }}
38
+
39
+ 3- Execution Code
40
+ {{
41
+ "type": "execution",
42
+ "description": "comprehensive description of what the execution code does"
43
+ }}
44
+
45
+ Analysis Guidelines:
46
+ 1- Imports Section:
47
+ - Identify each imported package
48
+ - Provide a clear, concise description of the package's purpose
49
+ - Include the standard library or third-party nature of the package
50
+ - Explain why the package is likely being used in this code
51
+
52
+ 2- Functions Section:
53
+ - List each function in the order they appear
54
+ - Describe the function's:
55
+ * Primary purpose
56
+ * Input parameters
57
+ * Return value (if any)
58
+ * Key operations performed
59
+ - Highlight any notable algorithms or logic within the function
60
+
61
+ 3- Execution Code Section:
62
+ - Describe the overall flow of the code
63
+ - Explain how functions are called
64
+ - Detail any data processing, computations, or side effects
65
+ - Provide context on the script's main objective
66
+
67
+ Important Notes:
68
+ - Use valid JSON format for output
69
+ - Be precise and technical in descriptions
70
+ - Use clear, professional language
71
+ - Avoid unnecessary verbosity
72
+ - Focus on explaining the code's functionality and purpose
73
  """
74
 
75
+ # describe_imports = """You are an expert {code_language} developer.
76
+ # Your will be given code lines that import packages.
77
+ # Your role is to give a brief description of each package
78
 
79
+ # You have access to the following tool and you MUST use it:
80
+ # search_pypi: Use this to get information about Python packages from PyPI.
 
 
81
 
82
+ # For each import:
83
+ # 1. Extract the main package name
84
+ # 2. Use the search_pypi tool to get package information by calling "search_pypi(package_name)"
85
+ # 3. Combine the information into a clear description
86
+ # 4. If the retuned value of tool is empty use your own knowledge
87
+ # 5. If you have no knowledge for this package then it's description should be "I don't know details about this package"
88
 
89
+ # You must respond in the following JSON format:
90
+ # {{"Imported_Packages": [
91
+ # {{"name": "package1", "desc": "brief description of package1"}},
92
+ # {{"name": "package2", "desc": "brief description of package2"}}
93
+ # ]}}
94
+
95
+ # Rules for the output:
96
+ # 1. Use valid JSON format
97
+ # 2. Package names should be the exact names from the imports
98
+ # 3. Descriptions should be brief and clear
99
+ # 4. Do not include any text outside the JSON structure
100
+ # """
101
+
102
+ # documenter_prompt = """You are an expert code documenter.
103
+ # Your role is to write a well structured document that describes code functionality.
104
+
105
+ documenter_prompt = """
106
+ Create a comprehensive Word document from the provided JSON input describing a Python script.
107
+
108
+ Document Requirements:
109
+ 1. Title should reflect the script's primary purpose
110
+ 2. Organize content into logical sections:
111
+ - Imports
112
+ - Functions
113
+ - Execution Mechanism
114
+ - Optional: Technical Insights and Potential Improvements
115
+
116
+ For Each Section:
117
+ - Explain the purpose and functionality
118
+ - Provide technical details
119
+ - Use professional technical writing style
120
+ - Include function signatures and parameter descriptions
121
+ - Break down complex descriptions into clear, concise points
122
+
123
+ Formatting Guidelines:
124
+ - Use a clean, professional Word document template
125
+ - Ensure consistent font and spacing
126
+ - Use bold text for emphasis
127
+ - Create bulleted or numbered lists for detailed explanations
128
+ - Include any available descriptions or comments from the JSON input
129
+
130
+ Specific Section Handling:
131
+ - Imports: Explain each imported library's purpose and specific use in the script
132
+ - Functions:
133
+ - Provide detailed function signatures
134
+ - Explain input parameters
135
+ - Describe return values
136
+ - Break down the function's purpose and mechanism
137
+ - Execution: Explain how the script is intended to run and its primary workflow
138
+
139
+ Additional Recommendations:
140
+ - If the JSON includes type information, incorporate it into the documentation
141
+ - Add context to explain the script's overall purpose
142
+ - Suggest potential improvements or extensions if the JSON provides enough context
143
+
144
+ Final Output:
145
+ - Fully formatted .docx file
146
+ - Comprehensive explanation of the script
147
+ - Technical yet readable documentation
148
+ - Output should be the document content only without any introduction
149
 
 
 
 
150
  """
151
+ # From the given context:
152
+ # 1- type: is the type of the code block (funciton, class, ..)
153
+ # 2- name: is the name of the code block
154
+ # 3- content: is the description of the code block
155
+
156
+ # Instructions:
157
+ # Write a docx document with the following structure Heading 1(type) -> Heading 2(name) -> content
158
+
159
+ # Rules for the output:
160
+ # 1. Don't write information out of context
161
+ # 2. If needed, structure long responses in lists and sections
162
+
163
+ # <context>
164
+ # {context}
165
+ # </context>
166
+ # """
167
 
168
  main_prompt = """You are an expert {code_language} developer.
169
  Your role is to answer user's questions about code and its description that will be given to you in context.
prompts.py:Zone.Identifier ADDED
File without changes
states.py:Zone.Identifier ADDED
File without changes
tools.py CHANGED
@@ -3,6 +3,8 @@ import requests
3
  import json
4
  from docx import Document
5
  import re
 
 
6
 
7
 
8
  @tool
@@ -30,22 +32,50 @@ def search_pypi(package_name: str) -> str:
30
  return f"Could not find package information: {str(e)}"
31
 
32
  # @tool
33
- def write_to_docx(documentation_text: str) -> str:
34
- """
35
- Writes the AI-generated documentation to a .docx file and returns the file path.
36
- """
37
- doc = Document()
38
- # doc.add_heading("Code Documentation", level=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
- lines = documentation_text.split("\n")
 
 
 
 
 
41
  for line in lines:
42
- if line.startswith("# "): # Section Heading
43
- doc.add_heading(line[2:], level=1)
44
- elif line.startswith("## "): # Subsection Heading
45
  doc.add_heading(line[3:], level=2)
46
- else: # Normal paragraph
 
 
 
 
 
 
 
 
 
 
47
  doc.add_paragraph(line)
48
-
49
- file_path = "generated_documentation.docx"
50
- doc.save(file_path)
51
- return file_path
 
3
  import json
4
  from docx import Document
5
  import re
6
+ from langchain_core.messages import BaseMessage, HumanMessage, AIMessage, SystemMessage
7
+
8
 
9
 
10
  @tool
 
32
  return f"Could not find package information: {str(e)}"
33
 
34
  # @tool
35
+ # def write_to_docx(documentation_text: str) -> str:
36
+ # """
37
+ # Writes the AI-generated documentation to a .docx file and returns the file path.
38
+ # """
39
+ # doc = Document()
40
+ # # doc.add_heading("Code Documentation", level=1)
41
+
42
+ # lines = documentation_text.split("\n")
43
+ # for line in lines:
44
+ # if line.startswith("# "): # Section Heading
45
+ # doc.add_heading(line[2:], level=1)
46
+ # elif line.startswith("## "): # Subsection Heading
47
+ # doc.add_heading(line[3:], level=2)
48
+ # else: # Normal paragraph
49
+ # doc.add_paragraph(line)
50
+
51
+ # file_path = "generated_documentation.docx"
52
+ # doc.save(file_path)
53
+ # return file_path
54
 
55
+ def write_to_docx(state):
56
+ text = state['messages'][-1].content
57
+ filename = 'generated_documentation.docx'
58
+ doc = Document()
59
+
60
+ lines = text.split("\n")
61
  for line in lines:
62
+ if line.startswith("### "):
63
+ doc.add_heading(line[4:], level=3)
64
+ elif line.startswith("## "):
65
  doc.add_heading(line[3:], level=2)
66
+ elif line.startswith("# "):
67
+ doc.add_heading(line[2:], level=1)
68
+ elif "**" in line:
69
+ bold_parts = re.split(r"(\*\*.*?\*\*)", line)
70
+ para = doc.add_paragraph()
71
+ for part in bold_parts:
72
+ if part.startswith("**") and part.endswith("**"):
73
+ para.add_run(part[2:-2]).bold = True
74
+ else:
75
+ para.add_run(part)
76
+ else:
77
  doc.add_paragraph(line)
78
+
79
+ # Save document
80
+ doc.save(filename)
81
+ return {"messages": [SystemMessage(content=[filename])]}
tools.py:Zone.Identifier ADDED
File without changes