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.

@@ -1,22 +1,70 @@
1
1
 
2
2
  import logging
3
3
  from pathlib import Path
4
- from typing import Callable, Optional
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 increase_token_usage, read_file, summarize_file
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 DEFAULT_TOKEN_USAGE, ProjectMetadata
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
- EVALUATION_README_SYSTEM_PROMPT = """
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
- ### **Step 1: Identify README type
121
-
122
- First, determine whether the provided README is a **project-level README** (typically at the root of a repository) or a **folder-level README** (typically inside subdirectories).
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
- ### **Evaluation Criteria**
182
+ ### **Output Format**
183
+ Your output must **exactly match** the following format. Do not add or omit any sections.
127
184
 
128
- #### If the README is a **project-level** file, evaluate it using the following criteria.
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
- For each criterion below, provide a brief assessment followed by specific, actionable comments for improvement.
201
+ ---
131
202
 
132
- **1. Project Clarity & Purpose**
133
- * **Assessment**: [Your evaluation of whether the project's purpose is clear.]
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
- **2. Installation Instructions**
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
- **3. Usage Instructions**
151
- * **Assessment**: [Your evaluation of the usage instructions.]
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
- **4. Contributing Guidelines**
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
- **5. License Information**
169
- * **Assessment**: [Your evaluation of the license information.]
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
- **6. Readability Analysis**
178
- * **Flesch Reading Ease**: `{flesch_reading_ease}` (A higher score is better, with 60-70 being easily understood by most adults).
179
- * **Flesch-Kincaid Grade Level**: `{flesch_kincaid_grade}` (Represents the US school-grade level needed to understand the text).
180
- * **Gunning Fog Index**: `{gunning_fog_index}` (A score above 12 is generally considered too hard for most people).
181
- * **SMOG Index**: `{smog_index}` (Estimates the years of education needed to understand the text).
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
- #### If if is a **folder-level** file, use the following criteria instead.
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 _structured_evaluate(self, free_readme_evaluations: dict[str, dict]):
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 free_readme_evaluations is None:
349
+ if readme_project_level is None:
326
350
  return None, total_token_usage
327
351
 
328
- license_path = "LICENSE"
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 free_readme_evaluations.keys():
340
- evaluation = free_readme_evaluations[readme_file]["evaluation"]
341
- if not evaluation["project_level"]:
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
- "structured_evaluation": StructuredEvaluationREADMEResult(
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
- "structured_reasoning_process": f"{readme_file} is an empty file.",
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
- "structured_evaluation": response,
393
- "structured_reasoning_process": reasoning_process,
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 _free_evaluate(self, files: list[str]):
401
- readme_files = files
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
- readme_evaluations = {}
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 len(readme_content.strip()) == 0:
414
- readme_evaluations[readme_file] = {
415
- "evaluation": {
416
- "project_level": not "/" in readme_file,
417
- "score": "Poor",
418
- "key_strengths": f"{readme_file} is an empty file.",
419
- "overall_improvement_suggestions": f"{readme_file} is an empty file.",
420
- },
421
- "reasoning_process": f"{readme_file} is an empty file.",
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
- continue
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
- readability = PyphenReadability()
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
- free_readme_evaluations, free_token_usage = self._free_evaluate(files)
462
- structured_readme_evaluations, structured_token_usage = self._structured_evaluate(free_readme_evaluations)
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 structured_readme_evaluations:
468
- combined_evaluations = {**free_readme_evaluations[f]}
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
- **free_readme_evaluations[f],
472
- **structured_readme_evaluations[f],
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):