bioguider 0.2.14__py3-none-any.whl → 0.2.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bioguider might be problematic. Click here for more details.
- bioguider/agents/agent_task.py +2 -2
- bioguider/agents/agent_utils.py +38 -54
- bioguider/agents/collection_observe_step.py +7 -2
- bioguider/agents/collection_task.py +1 -1
- bioguider/agents/collection_task_utils.py +1 -0
- bioguider/agents/common_agent.py +3 -25
- bioguider/agents/common_agent_2step.py +1 -1
- bioguider/agents/common_conversation.py +43 -0
- bioguider/agents/dockergeneration_observe_step.py +2 -1
- bioguider/agents/evaluation_installation_task.py +68 -99
- bioguider/agents/evaluation_readme_task.py +280 -182
- bioguider/agents/evaluation_submission_requirements_task.py +69 -54
- bioguider/agents/evaluation_task.py +1 -1
- bioguider/agents/identification_observe_step.py +7 -2
- bioguider/agents/identification_task.py +4 -0
- bioguider/agents/identification_task_utils.py +2 -0
- bioguider/agents/prompt_utils.py +5 -2
- bioguider/utils/constants.py +87 -1
- bioguider/utils/utils.py +45 -1
- {bioguider-0.2.14.dist-info → bioguider-0.2.16.dist-info}/METADATA +1 -1
- {bioguider-0.2.14.dist-info → bioguider-0.2.16.dist-info}/RECORD +23 -22
- {bioguider-0.2.14.dist-info → bioguider-0.2.16.dist-info}/LICENSE +0 -0
- {bioguider-0.2.14.dist-info → bioguider-0.2.16.dist-info}/WHEEL +0 -0
|
@@ -1,22 +1,70 @@
|
|
|
1
1
|
|
|
2
2
|
import logging
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Callable
|
|
4
|
+
from typing import Callable
|
|
5
5
|
from langchain.prompts import ChatPromptTemplate
|
|
6
6
|
from langchain_openai.chat_models.base import BaseChatOpenAI
|
|
7
|
-
from pydantic import BaseModel, Field
|
|
8
7
|
|
|
9
8
|
from bioguider.agents.prompt_utils import EVALUATION_INSTRUCTION
|
|
10
9
|
from bioguider.utils.gitignore_checker import GitignoreChecker
|
|
11
10
|
|
|
12
11
|
from ..utils.pyphen_utils import PyphenReadability
|
|
13
|
-
from bioguider.agents.agent_utils import
|
|
12
|
+
from bioguider.agents.agent_utils import (
|
|
13
|
+
read_file, read_license_file,
|
|
14
|
+
summarize_file
|
|
15
|
+
)
|
|
14
16
|
from bioguider.agents.common_agent_2step import CommonAgentTwoChainSteps
|
|
15
17
|
from bioguider.agents.evaluation_task import EvaluationTask
|
|
16
|
-
from bioguider.utils.constants import
|
|
18
|
+
from bioguider.utils.constants import (
|
|
19
|
+
DEFAULT_TOKEN_USAGE,
|
|
20
|
+
ProjectMetadata,
|
|
21
|
+
ProjectLevelEvaluationREADMEResult,
|
|
22
|
+
StructuredEvaluationREADMEResult,
|
|
23
|
+
FreeProjectLevelEvaluationREADMEResult,
|
|
24
|
+
FreeFolderLevelEvaluationREADMEResult,
|
|
25
|
+
EvaluationREADMEResult,
|
|
26
|
+
)
|
|
27
|
+
from bioguider.utils.utils import increase_token_usage
|
|
17
28
|
|
|
18
29
|
logger = logging.getLogger(__name__)
|
|
19
30
|
|
|
31
|
+
README_PROJECT_LEVEL_SYSTEM_PROMPT = """
|
|
32
|
+
You are an expert in evaluating the quality of README files in software repositories.
|
|
33
|
+
Your task is to analyze the provided README file and identify if it is a project-level README file or a folder-level README file.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
### **Classification Guidelines**
|
|
38
|
+
|
|
39
|
+
- **Project-level README**:
|
|
40
|
+
- Located in the repository root (e.g., `/`, `.github/`, or `docs/`).
|
|
41
|
+
- Contains project-wide content: overview, installation steps, global usage, badges, links to main docs or contributing guide.
|
|
42
|
+
|
|
43
|
+
- **Folder-level README**:
|
|
44
|
+
- Located inside a subfolder.
|
|
45
|
+
- Describes the specific folder: its purpose, contents, how to use or run what's inside, local instructions.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
### **Output Format**
|
|
50
|
+
Based solely on the file's **path**, **name**, and **content**, classify the README as either a **project-level** or **folder-level** README.
|
|
51
|
+
Output **exactly** the following format:
|
|
52
|
+
|
|
53
|
+
**FinalAnswer**
|
|
54
|
+
**Project-level:** [Yes / No]
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### **README Path**
|
|
59
|
+
{readme_path}
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
### **README content**
|
|
64
|
+
{readme_content}
|
|
65
|
+
|
|
66
|
+
"""
|
|
67
|
+
|
|
20
68
|
STRUCTURED_EVALUATION_README_SYSTEM_PROMPT = """
|
|
21
69
|
You are an expert in evaluating the quality of README files in software repositories.
|
|
22
70
|
Your task is to analyze the provided README file and generate a structured quality assessment based on the following criteria.
|
|
@@ -111,79 +159,71 @@ Your final report must **exactly match** the following format. Do not add or omi
|
|
|
111
159
|
|
|
112
160
|
"""
|
|
113
161
|
|
|
114
|
-
|
|
162
|
+
PROJECT_LEVEL_EVALUATION_README_SYSTEM_PROMPT = """
|
|
115
163
|
You are an expert in evaluating the quality of README files in software repositories.
|
|
116
|
-
Your task is to analyze the provided README file and generate a comprehensive quality report.
|
|
164
|
+
Your task is to analyze the provided project-level README file and generate a comprehensive quality report.
|
|
165
|
+
You will be given:
|
|
166
|
+
1. A README file.
|
|
167
|
+
2. A structured evaluation of the README file and its reasoning process.
|
|
117
168
|
|
|
118
169
|
---
|
|
119
170
|
|
|
120
|
-
### **
|
|
121
|
-
|
|
122
|
-
|
|
171
|
+
### **Instructions**
|
|
172
|
+
1. Based on the provided structured evaluation and its reasoning process, generate a free evaluation of the README file.
|
|
173
|
+
2. Focus on the explanation of assessment in structured evaluation and how to improve the README file based on the structured evaluation and its reasoning process.
|
|
174
|
+
* For each suggestion to improve the README file, you **must provide some examples** of the original text snippet and the improving comments.
|
|
175
|
+
3. For each item in the structured evaluation, provide a detailed assessment followed by specific, actionable comments for improvement.
|
|
176
|
+
4. Your improvement suggestions must also include the original text snippet and the improving comments.
|
|
177
|
+
5. Your improvement suggestions must also include suggestions to improve readability.
|
|
178
|
+
6. If you think the it is good enough, you can say so.
|
|
123
179
|
|
|
124
180
|
---
|
|
125
181
|
|
|
126
|
-
### **
|
|
182
|
+
### **Output Format**
|
|
183
|
+
Your output must **exactly match** the following format. Do not add or omit any sections.
|
|
127
184
|
|
|
128
|
-
|
|
185
|
+
**FinalAnswer**
|
|
186
|
+
**Available:**
|
|
187
|
+
<Your assessment and suggestion here>
|
|
188
|
+
**Readability:**
|
|
189
|
+
<Your assessment and suggestion here>
|
|
190
|
+
**Project Purpose:**
|
|
191
|
+
<Your assessment and suggestion here>
|
|
192
|
+
**Hardware and software spec and compatibility description:**
|
|
193
|
+
<Your assessment and suggestion here>
|
|
194
|
+
**Dependencies clearly stated:**
|
|
195
|
+
<Your assessment and suggestion here>
|
|
196
|
+
**License Information Included:**
|
|
197
|
+
<Your assessment and suggestion here>
|
|
198
|
+
** Code contributor / Author information included
|
|
199
|
+
<Your assessment and suggestion here>
|
|
129
200
|
|
|
130
|
-
|
|
201
|
+
---
|
|
131
202
|
|
|
132
|
-
**
|
|
133
|
-
|
|
134
|
-
* **Improvement Suggestions**:
|
|
135
|
-
* **Original text:** [Quote a specific line/section from the README.]
|
|
136
|
-
* **Improving comments:** [Provide your suggestions to improve clarity.]
|
|
137
|
-
* **Original text:** [Quote a specific line/section from the README.]
|
|
138
|
-
* **Improving comments:** [Provide your suggestions to improve clarity.]
|
|
139
|
-
...
|
|
203
|
+
### **Structured Evaluation and Reasoning Process**
|
|
204
|
+
{structured_evaluation}
|
|
140
205
|
|
|
141
|
-
|
|
142
|
-
* **Assessment**: [Your evaluation of the installation instructions.]
|
|
143
|
-
* **Improvement Suggestions**:
|
|
144
|
-
* **Original text:** [Quote text related to installation.]
|
|
145
|
-
* **Improving comments:** [Provide your suggestions.]
|
|
146
|
-
* **Original text:** [Quote text related to installation.]
|
|
147
|
-
* **Improving comments:** [Provide your suggestions.]
|
|
148
|
-
...
|
|
206
|
+
---
|
|
149
207
|
|
|
150
|
-
**
|
|
151
|
-
|
|
152
|
-
* **Improvement Suggestions**:
|
|
153
|
-
* **Original text:** [Quote text related to usage.]
|
|
154
|
-
* **Improving comments:** [Provide your suggestions.]
|
|
155
|
-
* **Original text:** [Quote text related to usage.]
|
|
156
|
-
* **Improving comments:** [Provide your suggestions.]
|
|
157
|
-
...
|
|
208
|
+
### **README Path**
|
|
209
|
+
{readme_path}
|
|
158
210
|
|
|
159
|
-
|
|
160
|
-
* **Assessment**: [Your evaluation of the contributing guidelines.]
|
|
161
|
-
* **Improvement Suggestions**:
|
|
162
|
-
* **Original text:** [Quote text related to contributions.]
|
|
163
|
-
* **Improving comments:** [Provide your suggestions.]
|
|
164
|
-
* **Original text:** [Quote text related to contributions.]
|
|
165
|
-
* **Improving comments:** [Provide your suggestions.]
|
|
166
|
-
...
|
|
211
|
+
---
|
|
167
212
|
|
|
168
|
-
**
|
|
169
|
-
|
|
170
|
-
* **Improvement Suggestions**:
|
|
171
|
-
* **Original text:** [Quote text related to the license.]
|
|
172
|
-
* **Improving comments:** [Provide your suggestions.]
|
|
173
|
-
* **Original text:** [Quote text related to the license.]
|
|
174
|
-
* **Improving comments:** [Provide your suggestions.]
|
|
175
|
-
...
|
|
213
|
+
### **README content**
|
|
214
|
+
{readme_content}
|
|
176
215
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
* **Assessment**: Based on these scores, evaluate the overall readability and technical complexity of the language used.
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
FOLDER_LEVEL_EVALUATION_README_SYSTEM_PROMPT = """
|
|
219
|
+
You are an expert in evaluating the quality of README files in software repositories.
|
|
220
|
+
Your task is to analyze the provided README file and generate a comprehensive quality report.
|
|
183
221
|
|
|
184
222
|
---
|
|
185
223
|
|
|
186
|
-
|
|
224
|
+
### **Evaluation Criteria**
|
|
225
|
+
|
|
226
|
+
The README file is a **folder-level** file, use the following criteria instead.
|
|
187
227
|
|
|
188
228
|
For each criterion below, provide a brief assessment followed by specific, actionable comments for improvement.
|
|
189
229
|
|
|
@@ -219,8 +259,6 @@ For each criterion below, provide a brief assessment followed by specific, actio
|
|
|
219
259
|
#### Your output **must exactly match** the following template:
|
|
220
260
|
|
|
221
261
|
**FinalAnswer**
|
|
222
|
-
|
|
223
|
-
* Project-Level README: Yes / No
|
|
224
262
|
* **Score:** [Poor / Fair / Good / Excellent]
|
|
225
263
|
* **Key Strengths**: <brief summary of the README's strongest points in 2-3 sentences>
|
|
226
264
|
* **Overall Improvement Suggestions:**
|
|
@@ -230,12 +268,10 @@ For each criterion below, provide a brief assessment followed by specific, actio
|
|
|
230
268
|
|
|
231
269
|
#### Notes
|
|
232
270
|
|
|
233
|
-
* **Project-Level README**: "Yes" if root-level; "No" if folder-level.
|
|
234
271
|
* **Score**: Overall quality rating, could be Poor / Fair / Good / Excellent.
|
|
235
272
|
* **Key Strengths**: Briefly highlight the README's strongest aspects.
|
|
236
273
|
* **Improvement Suggestions**: Provide concrete snippets and suggested improvements.
|
|
237
274
|
|
|
238
|
-
|
|
239
275
|
---
|
|
240
276
|
|
|
241
277
|
### **README path:**
|
|
@@ -247,56 +283,6 @@ For each criterion below, provide a brief assessment followed by specific, actio
|
|
|
247
283
|
{readme_content}
|
|
248
284
|
"""
|
|
249
285
|
|
|
250
|
-
|
|
251
|
-
class StructuredEvaluationREADMEResult(BaseModel):
|
|
252
|
-
available_score: Optional[bool]=Field(description="A boolean value, Is the README accessible and present?")
|
|
253
|
-
readability_score: Optional[str]=Field(description="A string value, could be `Poor`, `Fair`, `Good`, or `Excellent`")
|
|
254
|
-
readability_suggestions: Optional[str]=Field(description="Suggestions to improve readability if necessary")
|
|
255
|
-
project_purpose_score: Optional[bool]=Field(description="A boolean value. Is the project's goal or function clearly stated?")
|
|
256
|
-
project_purpose_suggestions: Optional[str]=Field(description="Suggestions if not clear")
|
|
257
|
-
hardware_and_software_spec_score: Optional[str]=Field(description="A string value, could be `Poor`, `Fair`, `Good`, or `Excellent`")
|
|
258
|
-
hardware_and_software_spec_suggestions: Optional[str]=Field(description="Suggestions if not clear")
|
|
259
|
-
dependency_score: Optional[str]=Field(description="A string value, could be `Poor`, `Fair`, `Good`, or `Excellent`")
|
|
260
|
-
dependency_suggestions: Optional[str]=Field(description="Suggestions if dependencies are not clearly stated")
|
|
261
|
-
license_score: Optional[bool]=Field(description="A boolean value, Are contributor or maintainer details provided?")
|
|
262
|
-
license_suggestions: Optional[str]=Field(description="Suggestions to improve license information")
|
|
263
|
-
contributor_author_score: Optional[bool]=Field(description="A boolean value. are contributors or author included?")
|
|
264
|
-
overall_score: str=Field(description="A overall scroll for the README quality, could be `Poor`, `Fair`, `Good`, or `Excellent`")
|
|
265
|
-
|
|
266
|
-
class EvaluationREADMEResult(BaseModel):
|
|
267
|
-
project_level: Optional[bool]=Field(description="A boolean value specifying if the README file is **project-level** README. TRUE: project-level, FALSE, folder-level")
|
|
268
|
-
score: Optional[str]=Field(description="An overall score")
|
|
269
|
-
key_strengths: Optional[str]=Field(description="A string specifying the key strengths of README file.")
|
|
270
|
-
overall_improvement_suggestions: Optional[list[str]]=Field(description="A list of overall improvement suggestions")
|
|
271
|
-
|
|
272
|
-
EvaluationREADMEResultSchema = {
|
|
273
|
-
"title": "EvaluationREADMEResult",
|
|
274
|
-
"type": "object",
|
|
275
|
-
"properties": {
|
|
276
|
-
"project_level": {
|
|
277
|
-
"anyOf": [{"type": "boolean"}, {"type": "null"}],
|
|
278
|
-
"description": "A boolean value specifying if the README file is **project-level** README. TRUE: project-level, FALSE: folder-level.",
|
|
279
|
-
"title": "Project Level"
|
|
280
|
-
},
|
|
281
|
-
"score": {
|
|
282
|
-
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
283
|
-
"description": "An overall score",
|
|
284
|
-
"title": "Score"
|
|
285
|
-
},
|
|
286
|
-
"key_strengths": {
|
|
287
|
-
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
288
|
-
"description": "A string specifying the key strengths of README file.",
|
|
289
|
-
"title": "Key Strengths",
|
|
290
|
-
},
|
|
291
|
-
"overall_improvement_suggestions": {
|
|
292
|
-
"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}],
|
|
293
|
-
"description": "A list of improvement suggestions",
|
|
294
|
-
"title": "Overall Improvement Suggestions"
|
|
295
|
-
}
|
|
296
|
-
},
|
|
297
|
-
"required": ["project_level", "score", "key_strengths", "overall_improvement_suggestions"]
|
|
298
|
-
}
|
|
299
|
-
|
|
300
286
|
class EvaluationREADMETask(EvaluationTask):
|
|
301
287
|
def __init__(
|
|
302
288
|
self,
|
|
@@ -310,7 +296,45 @@ class EvaluationREADMETask(EvaluationTask):
|
|
|
310
296
|
super().__init__(llm, repo_path, gitignore_path, meta_data, step_callback, summarized_files_db)
|
|
311
297
|
self.evaluation_name = "README Evaluation"
|
|
312
298
|
|
|
313
|
-
def
|
|
299
|
+
def _project_level_evaluate(self, readme_files: list[str]) -> tuple[dict, dict]:
|
|
300
|
+
"""
|
|
301
|
+
Evaluate if the README files are a project-level README file.
|
|
302
|
+
"""
|
|
303
|
+
total_token_usage = {**DEFAULT_TOKEN_USAGE}
|
|
304
|
+
project_level_evaluations = {}
|
|
305
|
+
for readme_file in readme_files:
|
|
306
|
+
full_path = Path(self.repo_path, readme_file)
|
|
307
|
+
readme_content = read_file(full_path)
|
|
308
|
+
if readme_content is None or len(readme_content.strip()) == 0:
|
|
309
|
+
logger.error(f"Error in reading file {readme_file}")
|
|
310
|
+
project_level_evaluations[readme_file] = {
|
|
311
|
+
"project_level": "/" in readme_file,
|
|
312
|
+
"project_level_reasoning_process": f"Error in reading file {readme_file}" \
|
|
313
|
+
if readme_content is None else f"{readme_file} is an empty file.",
|
|
314
|
+
}
|
|
315
|
+
continue
|
|
316
|
+
system_prompt = ChatPromptTemplate.from_template(
|
|
317
|
+
README_PROJECT_LEVEL_SYSTEM_PROMPT
|
|
318
|
+
).format(
|
|
319
|
+
readme_path=readme_file,
|
|
320
|
+
readme_content=readme_content,
|
|
321
|
+
)
|
|
322
|
+
agent = CommonAgentTwoChainSteps(llm=self.llm)
|
|
323
|
+
response, _, token_usage, reasoning_process = agent.go(
|
|
324
|
+
system_prompt=system_prompt,
|
|
325
|
+
instruction_prompt=EVALUATION_INSTRUCTION,
|
|
326
|
+
schema=ProjectLevelEvaluationREADMEResult,
|
|
327
|
+
)
|
|
328
|
+
total_token_usage = increase_token_usage(total_token_usage, token_usage)
|
|
329
|
+
self.print_step(step_output=f"README: {readme_file} project level README")
|
|
330
|
+
project_level_evaluations[readme_file] = {
|
|
331
|
+
"project_level": response.project_level,
|
|
332
|
+
"project_level_reasoning_process": reasoning_process,
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return project_level_evaluations, total_token_usage
|
|
336
|
+
|
|
337
|
+
def _structured_evaluate(self, readme_project_level: dict[str, dict] | None = None):
|
|
314
338
|
""" Evaluate README in structure:
|
|
315
339
|
available: bool
|
|
316
340
|
readability: score and suggestion
|
|
@@ -322,11 +346,10 @@ class EvaluationREADMETask(EvaluationTask):
|
|
|
322
346
|
overall score:
|
|
323
347
|
"""
|
|
324
348
|
total_token_usage = {**DEFAULT_TOKEN_USAGE}
|
|
325
|
-
if
|
|
349
|
+
if readme_project_level is None:
|
|
326
350
|
return None, total_token_usage
|
|
327
351
|
|
|
328
|
-
license_path =
|
|
329
|
-
license_content = read_file(Path(self.repo_path, license_path))
|
|
352
|
+
license_content, license_path = read_license_file(self.repo_path)
|
|
330
353
|
license_summarized_content = summarize_file(
|
|
331
354
|
llm=self.llm,
|
|
332
355
|
name=license_path,
|
|
@@ -336,9 +359,9 @@ class EvaluationREADMETask(EvaluationTask):
|
|
|
336
359
|
) if license_content is not None else "N/A"
|
|
337
360
|
license_path = license_path if license_content is not None else "N/A"
|
|
338
361
|
structured_readme_evaluations = {}
|
|
339
|
-
for readme_file in
|
|
340
|
-
|
|
341
|
-
if not
|
|
362
|
+
for readme_file in readme_project_level.keys():
|
|
363
|
+
project_level = readme_project_level[readme_file]["project_level"]
|
|
364
|
+
if not project_level:
|
|
342
365
|
continue
|
|
343
366
|
full_path = Path(self.repo_path, readme_file)
|
|
344
367
|
readme_content = read_file(full_path)
|
|
@@ -347,7 +370,7 @@ class EvaluationREADMETask(EvaluationTask):
|
|
|
347
370
|
continue
|
|
348
371
|
if len(readme_content.strip()) == 0:
|
|
349
372
|
structured_readme_evaluations[readme_file] = {
|
|
350
|
-
"
|
|
373
|
+
"evaluation": StructuredEvaluationREADMEResult(
|
|
351
374
|
available_score=False,
|
|
352
375
|
readability_score="Poor",
|
|
353
376
|
readability_suggestions="No readability provided",
|
|
@@ -362,7 +385,7 @@ class EvaluationREADMETask(EvaluationTask):
|
|
|
362
385
|
contributor_author_score=False,
|
|
363
386
|
overall_score="Poor",
|
|
364
387
|
),
|
|
365
|
-
"
|
|
388
|
+
"reasoning_process": f"{readme_file} is an empty file.",
|
|
366
389
|
}
|
|
367
390
|
continue
|
|
368
391
|
readability = PyphenReadability()
|
|
@@ -389,91 +412,166 @@ class EvaluationREADMETask(EvaluationTask):
|
|
|
389
412
|
self.print_step(step_output=f"README: {readme_file} structured evaluation")
|
|
390
413
|
self.print_step(step_output=reasoning_process)
|
|
391
414
|
structured_readme_evaluations[readme_file] = {
|
|
392
|
-
"
|
|
393
|
-
"
|
|
415
|
+
"evaluation": response,
|
|
416
|
+
"reasoning_process": reasoning_process,
|
|
394
417
|
}
|
|
395
418
|
total_token_usage = increase_token_usage(total_token_usage, token_usage)
|
|
396
419
|
|
|
397
420
|
return structured_readme_evaluations, total_token_usage
|
|
398
421
|
|
|
399
422
|
|
|
400
|
-
def
|
|
401
|
-
|
|
423
|
+
def _free_project_level_readme_evaluate(
|
|
424
|
+
self,
|
|
425
|
+
readme_file: str,
|
|
426
|
+
structured_reasoning_process: str,
|
|
427
|
+
) -> tuple[FreeProjectLevelEvaluationREADMEResult | None, dict, str]:
|
|
428
|
+
readme_path = Path(self.repo_path, readme_file)
|
|
429
|
+
readme_content = read_file(readme_path)
|
|
430
|
+
if readme_content is None:
|
|
431
|
+
logger.error(f"Error in reading file {readme_file}")
|
|
432
|
+
return None, {**DEFAULT_TOKEN_USAGE}, f"Error in reading file {readme_file}"
|
|
433
|
+
if readme_content.strip() == "":
|
|
434
|
+
return FreeProjectLevelEvaluationREADMEResult(
|
|
435
|
+
available=False,
|
|
436
|
+
readability="Poor",
|
|
437
|
+
project_purpose="Poor",
|
|
438
|
+
hardware_and_software_spec="Poor",
|
|
439
|
+
dependency="Poor",
|
|
440
|
+
), {**DEFAULT_TOKEN_USAGE}, f"{readme_file} is an empty file."
|
|
441
|
+
|
|
442
|
+
system_prompt = ChatPromptTemplate.from_template(
|
|
443
|
+
PROJECT_LEVEL_EVALUATION_README_SYSTEM_PROMPT
|
|
444
|
+
).format(
|
|
445
|
+
readme_path=readme_file,
|
|
446
|
+
readme_content=readme_content,
|
|
447
|
+
structured_evaluation=structured_reasoning_process,
|
|
448
|
+
)
|
|
449
|
+
agent = CommonAgentTwoChainSteps(llm=self.llm)
|
|
450
|
+
response, _, token_usage, reasoning_process = agent.go(
|
|
451
|
+
system_prompt=system_prompt,
|
|
452
|
+
instruction_prompt=EVALUATION_INSTRUCTION,
|
|
453
|
+
schema=FreeProjectLevelEvaluationREADMEResult,
|
|
454
|
+
)
|
|
455
|
+
self.print_step(step_output=f"README: {readme_file} free project level README")
|
|
456
|
+
self.print_step(step_output=reasoning_process)
|
|
457
|
+
return response, token_usage, reasoning_process
|
|
458
|
+
|
|
459
|
+
def _free_folder_level_readme_evaluate(
|
|
460
|
+
self,
|
|
461
|
+
readme_file: str,
|
|
462
|
+
) -> tuple[FreeFolderLevelEvaluationREADMEResult | None, dict, str]:
|
|
463
|
+
readme_path = Path(self.repo_path, readme_file)
|
|
464
|
+
readme_content = read_file(readme_path)
|
|
465
|
+
if readme_content is None:
|
|
466
|
+
logger.error(f"Error in reading file {readme_file}")
|
|
467
|
+
return None, {**DEFAULT_TOKEN_USAGE}, f"Error in reading file {readme_file}"
|
|
468
|
+
if readme_content.strip() == "":
|
|
469
|
+
return FreeFolderLevelEvaluationREADMEResult(
|
|
470
|
+
score="Poor",
|
|
471
|
+
key_strengths=f"{readme_file} is an empty file.",
|
|
472
|
+
overall_improvement_suggestions=[f"{readme_file} is an empty file."],
|
|
473
|
+
), {**DEFAULT_TOKEN_USAGE}, f"{readme_file} is an empty file."
|
|
474
|
+
|
|
475
|
+
readability = PyphenReadability()
|
|
476
|
+
flesch_reading_ease, flesch_kincaid_grade, gunning_fog_index, smog_index, \
|
|
477
|
+
_, _, _, _, _ = readability.readability_metrics(readme_content)
|
|
478
|
+
system_prompt = ChatPromptTemplate.from_template(
|
|
479
|
+
FOLDER_LEVEL_EVALUATION_README_SYSTEM_PROMPT
|
|
480
|
+
).format(
|
|
481
|
+
readme_path=readme_file,
|
|
482
|
+
readme_content=readme_content,
|
|
483
|
+
flesch_reading_ease=flesch_reading_ease,
|
|
484
|
+
flesch_kincaid_grade=flesch_kincaid_grade,
|
|
485
|
+
gunning_fog_index=gunning_fog_index,
|
|
486
|
+
smog_index=smog_index,
|
|
487
|
+
)
|
|
488
|
+
agent = CommonAgentTwoChainSteps(llm=self.llm)
|
|
489
|
+
response, _, token_usage, reasoning_process = agent.go(
|
|
490
|
+
system_prompt=system_prompt,
|
|
491
|
+
instruction_prompt=EVALUATION_INSTRUCTION,
|
|
492
|
+
schema=FreeFolderLevelEvaluationREADMEResult,
|
|
493
|
+
)
|
|
494
|
+
self.print_step(step_output=f"README: {readme_file} free folder level README")
|
|
495
|
+
self.print_step(step_output=reasoning_process)
|
|
496
|
+
return response, token_usage, reasoning_process
|
|
497
|
+
|
|
498
|
+
def _free_evaluate(
|
|
499
|
+
self,
|
|
500
|
+
readme_project_level: dict[str, dict],
|
|
501
|
+
structured_readme_evaluations: dict[str, dict]
|
|
502
|
+
):
|
|
503
|
+
readme_files = readme_project_level.keys()
|
|
402
504
|
if readme_files is None or len(readme_files) == 0:
|
|
403
505
|
return None, {**DEFAULT_TOKEN_USAGE}
|
|
404
506
|
|
|
405
|
-
|
|
507
|
+
free_readme_evaluations = {}
|
|
406
508
|
total_token_usage = {**DEFAULT_TOKEN_USAGE}
|
|
407
509
|
for readme_file in readme_files:
|
|
408
510
|
readme_path = Path(self.repo_path, readme_file)
|
|
511
|
+
project_level = readme_project_level[readme_file]["project_level"]
|
|
409
512
|
readme_content = read_file(readme_path)
|
|
410
513
|
if readme_content is None:
|
|
411
514
|
logger.error(f"Error in reading file {readme_file}")
|
|
412
515
|
continue
|
|
413
|
-
if
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
"
|
|
516
|
+
if project_level:
|
|
517
|
+
evaluation, token_usage, reasoning_process = self._free_project_level_readme_evaluate(
|
|
518
|
+
readme_file=readme_file,
|
|
519
|
+
structured_reasoning_process=structured_readme_evaluations[readme_file]["reasoning_process"],
|
|
520
|
+
)
|
|
521
|
+
if evaluation is None:
|
|
522
|
+
continue
|
|
523
|
+
free_readme_evaluations[readme_file] = {
|
|
524
|
+
"evaluation": evaluation,
|
|
525
|
+
"reasoning_process": reasoning_process,
|
|
422
526
|
}
|
|
423
|
-
|
|
527
|
+
total_token_usage = increase_token_usage(total_token_usage, token_usage)
|
|
528
|
+
|
|
529
|
+
else:
|
|
530
|
+
evaluation, token_usage, reasoning_process = self._free_folder_level_readme_evaluate(
|
|
531
|
+
readme_file=readme_file,
|
|
532
|
+
)
|
|
533
|
+
if evaluation is None:
|
|
534
|
+
continue
|
|
535
|
+
free_readme_evaluations[readme_file] = {
|
|
536
|
+
"evaluation": evaluation,
|
|
537
|
+
"reasoning_process": reasoning_process,
|
|
538
|
+
}
|
|
539
|
+
total_token_usage = increase_token_usage(total_token_usage, token_usage)
|
|
424
540
|
|
|
425
|
-
|
|
426
|
-
flesch_reading_ease, flesch_kincaid_grade, gunning_fog_index, smog_index, \
|
|
427
|
-
_, _, _, _, _ = readability.readability_metrics(readme_content)
|
|
428
|
-
system_prompt = ChatPromptTemplate.from_template(
|
|
429
|
-
EVALUATION_README_SYSTEM_PROMPT
|
|
430
|
-
).format(
|
|
431
|
-
readme_content=readme_content,
|
|
432
|
-
readme_path=readme_file,
|
|
433
|
-
flesch_reading_ease=flesch_reading_ease,
|
|
434
|
-
flesch_kincaid_grade=flesch_kincaid_grade,
|
|
435
|
-
gunning_fog_index=gunning_fog_index,
|
|
436
|
-
smog_index=smog_index,
|
|
437
|
-
)
|
|
438
|
-
# conversation = CommonConversation(llm=self.llm)
|
|
439
|
-
agent = CommonAgentTwoChainSteps(llm=self.llm)
|
|
440
|
-
response, _, token_usage, reasoning_process = agent.go(
|
|
441
|
-
system_prompt=system_prompt,
|
|
442
|
-
instruction_prompt=EVALUATION_INSTRUCTION,
|
|
443
|
-
schema=EvaluationREADMEResultSchema,
|
|
444
|
-
)
|
|
445
|
-
response = EvaluationREADMEResult(**response)
|
|
446
|
-
self.print_step(step_output=f"README: {readme_file} free evaluation")
|
|
447
|
-
self.print_step(step_output=reasoning_process)
|
|
448
|
-
readme_evaluations[readme_file] = {
|
|
449
|
-
"evaluation": {
|
|
450
|
-
"project_level": response.project_level,
|
|
451
|
-
"score": response.score,
|
|
452
|
-
"key_strengths": response.key_strengths,
|
|
453
|
-
"overall_improvement_suggestions": response.overall_improvement_suggestions,
|
|
454
|
-
},
|
|
455
|
-
"reasoning_process": reasoning_process
|
|
456
|
-
}
|
|
457
|
-
total_token_usage = increase_token_usage(total_token_usage, token_usage)
|
|
458
|
-
return readme_evaluations, total_token_usage
|
|
541
|
+
return free_readme_evaluations, total_token_usage
|
|
459
542
|
|
|
460
|
-
def _evaluate(self, files: list[str]) -> tuple[dict, dict, list[str]]:
|
|
461
|
-
|
|
462
|
-
|
|
543
|
+
def _evaluate(self, files: list[str]) -> tuple[dict[str, EvaluationREADMEResult], dict, list[str]]:
|
|
544
|
+
total_token_usage = {**DEFAULT_TOKEN_USAGE}
|
|
545
|
+
project_level_evaluations, project_level_token_usage = self._project_level_evaluate(files)
|
|
546
|
+
total_token_usage = increase_token_usage(total_token_usage, project_level_token_usage)
|
|
547
|
+
structured_readme_evaluations, structured_token_usage = self._structured_evaluate(project_level_evaluations)
|
|
548
|
+
total_token_usage = increase_token_usage(total_token_usage, structured_token_usage)
|
|
549
|
+
free_readme_evaluations, free_token_usage = self._free_evaluate(project_level_evaluations, structured_readme_evaluations)
|
|
550
|
+
total_token_usage = increase_token_usage(total_token_usage, free_token_usage)
|
|
463
551
|
|
|
464
552
|
# combine result
|
|
465
553
|
combined_evaluations = {}
|
|
466
554
|
for f in files:
|
|
467
|
-
if not f in
|
|
468
|
-
|
|
555
|
+
if not f in free_readme_evaluations:
|
|
556
|
+
continue
|
|
557
|
+
project_level = project_level_evaluations[f]["project_level"]
|
|
558
|
+
if project_level:
|
|
559
|
+
combined_evaluations[f] = EvaluationREADMEResult(
|
|
560
|
+
project_level=project_level,
|
|
561
|
+
structured_evaluation=structured_readme_evaluations[f]["evaluation"],
|
|
562
|
+
free_evaluation=free_readme_evaluations[f]["evaluation"],
|
|
563
|
+
structured_reasoning_process=structured_readme_evaluations[f]["reasoning_process"],
|
|
564
|
+
free_reasoning_process=free_readme_evaluations[f]["reasoning_process"],
|
|
565
|
+
)
|
|
469
566
|
else:
|
|
470
|
-
combined_evaluations[f] =
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
567
|
+
combined_evaluations[f] = EvaluationREADMEResult(
|
|
568
|
+
project_level=project_level,
|
|
569
|
+
structured_evaluation=None,
|
|
570
|
+
free_evaluation=free_readme_evaluations[f]["evaluation"],
|
|
571
|
+
structured_reasoning_process=None,
|
|
572
|
+
free_reasoning_process=free_readme_evaluations[f]["reasoning_process"],
|
|
573
|
+
)
|
|
474
574
|
|
|
475
|
-
total_token_usage = increase_token_usage(free_token_usage, structured_token_usage)
|
|
476
|
-
|
|
477
575
|
return combined_evaluations, total_token_usage, files
|
|
478
576
|
|
|
479
577
|
def _collect_files(self):
|