Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added osa_tool/assets/notosans-sc-black.ttf
Binary file not shown.
Binary file added osa_tool/assets/notosans-sc-bold.ttf
Binary file not shown.
Binary file added osa_tool/assets/notosans-sc.ttf
Binary file not shown.
5 changes: 4 additions & 1 deletion osa_tool/config/prompts/analysis.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ RULES:
- Be strictly factual about file presence
- Check for the presence of the directory with tests
- Prioritize 3 most critical recommendations

- Write text in values on {target_language}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep file names out of translation

For non-English reports this blanket instruction applies to every JSON value, including structure.missing_files, which is later joined directly into the PDF. That can cause the model to translate concrete repository paths or filenames such as tests/requirements.txt, so the report can name files that do not actually exist instead of preserving the missing artifact names verbatim. Add an explicit exception for file, directory, package, and operation identifiers.

Useful? React with 👍 / 👎.

"""

after_report_summary_from_events_prompt = """
Expand All @@ -63,6 +63,7 @@ REQUIREMENTS:
- Keep it concise (about two short paragraphs)
- Do not use markdown
- Do not use bullet points or lists
- Write it on target language: {target_language}

OUTPUT:
Return ONLY JSON matching the system message schema.
Expand All @@ -81,6 +82,8 @@ REQUIREMENTS:
- Each performed operation must appear in exactly one block
- "tasks" must list operation names exactly as provided (strings)
- Do not invent operations
- Write descriptions on target language: {target_language}
- Use original task names, do not translate it

OUTPUT:
Return ONLY JSON matching the system message schema.
Expand Down
10 changes: 7 additions & 3 deletions osa_tool/config/settings/arguments.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,16 @@ arguments:
aliases: [ "--validate-doc" ]
type: flag
description: "Check whether the experiments proposed in an attached documentation file can be reproduced using the selected repository."
artefacts_language:
aliases: [ "--artefacts-language" ]
type: str
description: "Generate reports on selected language"
Comment thread
DRMPN marked this conversation as resolved.
Outdated

settings:
use_single_model:
aliases: [ "--use-single-model" ]
type: flag
description: "Use the same model for all tasks (from default configuration)."
aliases: [ "--use-single-model" ]
type: flag
description: "Use the same model for all tasks (from default configuration)."

config_file:
aliases: [ "--config-file" ]
Expand Down
1 change: 1 addition & 0 deletions osa_tool/config/settings/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ validate_paper = false
validate_doc = false
incremental = false
target_files = []
artefacts_language = "English"

#Workflow Settings
[workflows]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@


class TextGenerator:
def __init__(self, config_manager: ConfigManager, metadata: RepositoryMetadata):
def __init__(
self, config_manager: ConfigManager, metadata: RepositoryMetadata, target_language: str = "English"
) -> None:
self.config_manager = config_manager
self.model_settings = self.config_manager.get_model_settings("general")
self.sourcerank = SourceRank(self.config_manager)
Expand All @@ -35,6 +37,7 @@ def __init__(self, config_manager: ConfigManager, metadata: RepositoryMetadata):
self.model_handler: ModelHandler = ModelHandlerFactory.build(self.model_settings)
self.repo_url = self.config_manager.get_git_settings().repository
self.base_path = os.path.join(os.getcwd(), parse_folder_name(self.repo_url))
self.target_language = target_language

def make_request(self) -> RepositoryReport:
"""
Expand All @@ -50,6 +53,7 @@ def make_request(self) -> RepositoryReport:
repository_tree=self.sourcerank.tree,
presence_files=self._extract_presence_files(),
readme_content=extract_readme_content(self.base_path),
target_language=self.target_language,
)

try:
Expand Down Expand Up @@ -98,13 +102,15 @@ def __init__(
config_manger: ConfigManager,
completed_tasks: list[tuple[str, bool]],
task_results: dict[str, dict] | None = None,
target_language: str = "English",
) -> None:
self.config_manager = config_manger
self.model_settings = self.config_manager.get_model_settings("general")
self.prompts = self.config_manager.get_prompts()
self.completed_tasks = completed_tasks
self.task_results = task_results or {}
self.model_handler: ModelHandler = ModelHandlerFactory.build(self.model_settings)
self.target_language = target_language

def make_request(self) -> AfterReport:
"""
Expand All @@ -123,6 +129,7 @@ def make_request(self) -> AfterReport:
summary_prompt = PromptBuilder.render(
self.prompts.get("analysis.after_report_summary_from_events_prompt"),
operations=operations_text,
target_language=self.target_language,
)
summary_obj: AfterReportSummary = self.model_handler.run_chain(
prompt=summary_prompt,
Expand All @@ -136,6 +143,7 @@ def make_request(self) -> AfterReport:
blocks_prompt = PromptBuilder.render(
self.prompts.get("analysis.after_report_blocks_from_events_prompt"),
operations=operations_text,
target_language=self.target_language,
)
blocks_plan: AfterReportBlocksPlan = self.model_handler.run_chain(
prompt=blocks_prompt,
Expand Down
167 changes: 167 additions & 0 deletions osa_tool/operations/analysis/repository_report/report_localization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
from osa_tool.operations.analysis.repository_report.response_validation import YesNoPartial

TRANSLATIONS = {
"English": {
Comment on lines +3 to +4

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нам обязательно для каждого языка и модуля заполнять эти значения?

Если добавится поддержка китайского, то нужно будет ключ - значение и для него прописывать?

Я думаю может это ЛЛМке на откуп отдать?

Если у нас появятся другие значения, то как их добавлять? Может в конфиг или еще куда-то это вынести, а не в константой?

"report_header": "Repository Analysis Report",
"statistics": "Statistics",
"values": "Values",
"stars_count": "Stars Count",
"forks_count": "Forks Count",
"issues_count": "Issues Count",
"metric": "Metric",
"readme_presence": "README Presence",
"license_presence": "License Presence",
"documentation_presence": "Documentation Presence",
"examples_presence": "Examples Presence",
"requirements_presence": "Requirements Presence",
"tests_presence": "Tests Presence",
"description_presence": "Description Presence",
"repository_name": "Repository Name",
"owner": "Owner",
"created_at": "Created at",
"repository_structure": "Repository Structure",
"compliance": "Compliance",
"missing_files": "Missing Files",
"organization": "Organization",
"readme_analysis": "README Analysis",
"quality": "Quality",
"documentation": "Documentation",
"test_present": "Test present",
"documentation_quality": "Document quality",
"outdated_content": "Outdated content",
"key_shortcomings": "Key Shortcomings",
"recommendations": "Recommendations",
"readme_quality": "text",
"project_description": "Project description",
"installation": "Installation",
"usage_examples": "Usage examples",
"contribution_guidelines": "Contribution guidelines",
"license_specified": "License specified",
"badges_present": "Badges present",
"summary_header": "OSA Work Summary",
"what_have_been_done": "What have been done",
"report_by_tasks": "Report by tasks",
"yes": "Yes",
"no": "No",
"partial": "Partial",
"report": "Report",
"translate_dirs": "Translate dirs",
"convert_notebooks": "Convert notebooks",
"translate_readme": "Translate readme",
"ensure_license": "Ensure license",
"community_docs": "Community docs",
"docstring": "Docstring",
"ignore_list": "Ignore list",
"incremental": "Incremental",
"target_files": "Target files",
"readme": "Readme",
"refine_readme": "Refine readme",
"requirements": "Requirements",
"organize": "Organize",
"about": "About",
"validate_paper": "Validate paper",
"validate_doc": "Validate doc",
"author": "Author",
"generate_workflows": "Generate workflows",
"include_tests": "Include tests",
"include_black": "Include black",
"include_pep8": "Include pep8",
"include_autopep8": "Include autopep8",
"include_fix_pep8": "Include fix pep8",
"include_pypi": "Include pypi",
"python_versions": "Python versions",
"pep8_tool": "Pep8 tool",
"use_poetry": "Use poetry",
"include_codecov": "Include codecov",
},
"Russian": {
"report_header": "Отчет об анализе репозитория",
"statistics": "Статистика",
"values": "Значения",
"stars_count": "Количество звезд",
"forks_count": "Количество форков",
"issues_count": "Количество issues",
"metric": "Метрика",
"readme_presence": "Наличие README",
"license_presence": "Наличие лицензии",
"documentation_presence": "Наличие документации",
"examples_presence": "Наличие примеров",
"requirements_presence": "Наличие requirements",
"tests_presence": "Наличие тестов",
"description_presence": "Наличие описания",
"repository_name": "Имя репозитория",
"owner": "Владелец",
"created_at": "Создан",
"repository_structure": "Структура репозитория",
"compliance": "Соответствие стандартам",
"missing_files": "Отсутствующие файлы",
"organization": "Организация",
"readme_analysis": "Анализ README",
"quality": "Качество",
"documentation": "Документация",
"test_present": "Наличие тестов",
"documentation_quality": "Качество документации",
"outdated_content": "Устаревший контент",
"key_shortcomings": "Ключевые недостатки",
"recommendations": "Рекомендации",
"readme_quality": "текст",
"project_description": "Описание проекта",
"installation": "Установка",
"usage_examples": "Примеры использования",
"contribution_guidelines": "Руководство по внесению вклада",
"license_specified": "Лицензия указана",
"badges_present": "Наличие бейджей",
"summary_header": "Сводка работы OSA",
"what_have_been_done": "Что было сделано",
"report_by_tasks": "Отчет по задачам",
"yes": "Да",
"no": "Нет",
"partial": "Частично",
"report": "Отчет",
"translate_dirs": "Перевод директорий",
"convert_notebooks": "Конвертация ноутбуков",
"translate_readme": "Перевод README",
"ensure_license": "Обеспечение наличия лицензии",
"community_docs": "Документы сообщества",
"docstring": "Строки документации",
"ignore_list": "Список исключений",
"incremental": "Инкрементальный режим",
"target_files": "Целевые файлы",
"readme": "Файл README",
"refine_readme": "Улучшение README",
"requirements": "Требования (зависимости)",
"organize": "Организация структуры",
"about": "Раздел «О проекте»",
"validate_paper": "Проверка статьи (paper)",
"validate_doc": "Проверка документации",
"author": "Автор",
"generate_workflows": "Генерация рабочих процессов (workflows)",
"include_tests": "Включить тесты",
"include_black": "Использовать Black",
"include_pep8": "Использовать PEP8",
"include_autopep8": "Использовать autopep8",
"include_fix_pep8": "Включить автоисправление PEP8",
"include_pypi": "Интеграция с PyPI",
"python_versions": "Версии Python",
"pep8_tool": "Инструмент проверки PEP8",
"use_poetry": "Использовать Poetry",
"include_codecov": "Интеграция с Codecov",
},
}


class ReportTranslationManager:
def __init__(self, target_language):
self.target_language = target_language if target_language in TRANSLATIONS.keys() else "English"

def get(self, key: str) -> str | None:
return TRANSLATIONS[self.target_language].get(key)

def yes_no_partial(self, key: YesNoPartial) -> str | None:
if key == YesNoPartial.YES:
return self.get("yes")
elif key == YesNoPartial.NO:
return self.get("no")
elif key == YesNoPartial.PARTIAL:
return self.get("partial")
return None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve unknown Yes/No/Partial values

When the model returns Unknown for a YesNoPartial field, or when TextGenerator.make_request() falls back to the default RepositoryReport after a parse failure, this fallback returns None. The report renderer then prints None for README/test checks that are actually unknown; before this change those enum values were rendered as Unknown, so the generated PDF now misreports indeterminate analysis results instead of preserving that state.

Useful? React with 👍 / 👎.

Loading
Loading