Delete directory 'solutions/69dd4221f309a98be0006b2e_сырой_текст_задания___плоская_карточка'
This commit is contained in:
@@ -1,91 +0,0 @@
|
||||
# Сырой текст задания → Плоская карточка
|
||||
|
||||
## Описание
|
||||
Данный проект реализует конвертацию «сырого» текста задания в формат **плоской карточки** (flat card). Карточка представляет собой упрощённую, визуально чистую версию исходного документа, пригодную для быстрого просмотра и дальнейшего использования в системах управления задачами или в качестве шаблона для презентаций.
|
||||
|
||||
## Структура проекта
|
||||
```
|
||||
project/
|
||||
├── src/
|
||||
│ ├── main.py # Точка входа – скрипт конвертации
|
||||
│ ├── utils.py # Вспомогательные функции (парсинг, форматирование)
|
||||
│ └── templates/ # Шаблоны карточек в формате Markdown / HTML
|
||||
├── tests/
|
||||
│ └── test_main.py # Юнит‑тесты
|
||||
├── requirements.txt # Зависимости проекта
|
||||
└── README.md # Это файл
|
||||
```
|
||||
|
||||
## Установка зависимостей
|
||||
|
||||
```bash
|
||||
# Создайте виртуальное окружение (рекомендуется)
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate # Windows: .\.venv\Scripts\activate
|
||||
|
||||
# Установите зависимости из requirements.txt
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
`requirements.txt` содержит только необходимые библиотеки, например:
|
||||
|
||||
```text
|
||||
Jinja2>=3.0 # для шаблонизации карточек
|
||||
Markdown>=3.4 # при необходимости конвертации Markdown в HTML
|
||||
```
|
||||
|
||||
## Запуск
|
||||
|
||||
### Конвертация одного файла
|
||||
```bash
|
||||
python src/main.py path/to/raw_task.txt --output path/to/card.md
|
||||
```
|
||||
- `path/to/raw_task.txt` – путь к исходному файлу с «сырым» текстом задания.
|
||||
- `--output` (необязательно) – куда сохранить результат. Если не указано, вывод будет в stdout.
|
||||
|
||||
### Конвертация всех файлов из каталога
|
||||
```bash
|
||||
python src/main.py path/to/raw_tasks/ --recursive --output-dir path/to/cards/
|
||||
```
|
||||
- `--recursive` обрабатывает все `.txt` файлы внутри указанного каталога и его подпапок.
|
||||
- `--output-dir` – каталог, куда будут сохранены карточки.
|
||||
|
||||
## Пример использования
|
||||
|
||||
```bash
|
||||
# Предположим, у нас есть файл task1.txt со следующим содержанием:
|
||||
#
|
||||
# # Задача 1
|
||||
# Описание: Написать скрипт, который конвертирует сырой текст в плоскую карточку.
|
||||
# Требования:
|
||||
# - Использовать Python 3.8+
|
||||
# - Сохранять результат в Markdown
|
||||
|
||||
python src/main.py task1.txt --output card_task1.md
|
||||
```
|
||||
|
||||
После выполнения будет создан файл `card_task1.md` со следующим содержимым:
|
||||
|
||||
```markdown
|
||||
# Задача 1
|
||||
|
||||
**Описание:**
|
||||
Написать скрипт, который конвертирует сырой текст в плоскую карточку.
|
||||
|
||||
## Требования
|
||||
- Использовать Python 3.8+
|
||||
- Сохранять результат в Markdown
|
||||
```
|
||||
|
||||
## Тесты
|
||||
|
||||
```bash
|
||||
pytest tests/
|
||||
```
|
||||
|
||||
Все тесты находятся в каталоге `tests/` и проверяют корректность парсинга, форматирования и генерации карточек.
|
||||
|
||||
## Лицензия
|
||||
MIT License – см. файл `LICENSE`.
|
||||
|
||||
---
|
||||
-85
@@ -1,85 +0,0 @@
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List
|
||||
|
||||
# ------------------------------
|
||||
# Модель карточки задания
|
||||
# ------------------------------
|
||||
class TaskCard(BaseModel):
|
||||
title: str = Field(..., description="Название задания")
|
||||
subject: str = Field(..., description="Тема/область задачи")
|
||||
deadline_hint: str = Field(..., description="Подсказка по дедлайну")
|
||||
deliverable_type: str = Field(
|
||||
..., description="Тип сдачи (отчёт, код и т.д.)"
|
||||
)
|
||||
grading_hints: List[str] = Field(
|
||||
..., description="Ключевые критерии оценки"
|
||||
)
|
||||
|
||||
# ------------------------------
|
||||
# Интеграция с LangChain
|
||||
# ------------------------------
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_core.prompts import PromptTemplate
|
||||
from langchain_core.output_parsers import PydanticOutputParser
|
||||
|
||||
parser = PydanticOutputParser(pydantic_object=TaskCard)
|
||||
|
||||
prompt_template = """
|
||||
You are an assistant that extracts structured information from a natural language description of a task.
|
||||
Return the data in JSON format matching the following schema:
|
||||
{format_instructions}
|
||||
Input: {input_text}
|
||||
"""
|
||||
|
||||
prompt = PromptTemplate(
|
||||
template=prompt_template,
|
||||
input_variables=["input_text"],
|
||||
partial_variables={"format_instructions": parser.get_format_instructions()},
|
||||
)
|
||||
|
||||
# ------------------------------
|
||||
# Настройка LLM
|
||||
# ------------------------------
|
||||
def get_llm() -> ChatOpenAI:
|
||||
"""
|
||||
Создаёт экземпляр модели OpenAI.
|
||||
Ключ берётся из переменной окружения OPENAI_API_KEY.
|
||||
"""
|
||||
api_key = os.getenv("OPENAI_API_KEY")
|
||||
if not api_key:
|
||||
raise RuntimeError(
|
||||
"Переменная окружения OPENAI_API_KEY не найдена. "
|
||||
"Пожалуйста, установите ключ API."
|
||||
)
|
||||
return ChatOpenAI(model="gpt-4o-mini", temperature=0.2, openai_api_key=api_key)
|
||||
|
||||
# ------------------------------
|
||||
# Основная цепочка
|
||||
# ------------------------------
|
||||
def build_chain() -> PromptTemplate:
|
||||
llm = get_llm()
|
||||
return prompt | llm | parser
|
||||
|
||||
# ------------------------------
|
||||
# Тестовый запуск
|
||||
# ------------------------------
|
||||
if __name__ == "__main__":
|
||||
# Загрузка переменных окружения из .env, если файл существует
|
||||
try:
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv(dotenv_path=Path(".env"))
|
||||
except Exception:
|
||||
pass # Если dotenv не установлен – просто продолжим
|
||||
|
||||
raw_text = (
|
||||
"Сдайте к пятнице мини-отчёт по LangChain: 2 страницы, упор на агентов. "
|
||||
"Оценка: за полноту и за пример кода."
|
||||
)
|
||||
|
||||
chain = build_chain()
|
||||
result = chain.invoke({"input_text": raw_text})
|
||||
print(result.model_dump(indent=4))
|
||||
-1
@@ -1 +0,0 @@
|
||||
<|channel|>commentary to=repo_browser.print_tree code<|message|>{"path": "", "depth": 3}
|
||||
@@ -1,65 +0,0 @@
|
||||
from typing import List
|
||||
from pydantic import BaseModel, Field
|
||||
from langchain_core.prompts import PromptTemplate
|
||||
from langchain_core.output_parsers import PydanticOutputParser
|
||||
from langchain_openai import ChatOpenAI
|
||||
|
||||
|
||||
class AssignmentCard(BaseModel):
|
||||
title: str = Field(..., description="Название задания одной фразой")
|
||||
subject: str = Field(..., description="Учебная дисциплина или тема")
|
||||
deadline_hint: str | None = Field(
|
||||
None,
|
||||
description="Срок выполнения в произвольной форме, если упомянут",
|
||||
)
|
||||
deliverable_type: str = Field(
|
||||
...,
|
||||
description="Что нужно сдать: отчёт, код, презентация и т.п.",
|
||||
)
|
||||
grading_hints: List[str] | None = Field(
|
||||
default_factory=list,
|
||||
description="Критерии оценки, которые явно названы в тексте",
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
output_parser = PydanticOutputParser(pydantic_object=AssignmentCard)
|
||||
|
||||
template = PromptTemplate(
|
||||
template=(
|
||||
"Прочитай описание учебного задания и заполни все поля карточки.\n\n"
|
||||
"Описание:\n{raw_text}\n\n"
|
||||
"Верни ответ строго в JSON без лишних пояснений.\n"
|
||||
"{format_instructions}"
|
||||
),
|
||||
input_variables=["raw_text"],
|
||||
partial_variables={
|
||||
"format_instructions": output_parser.get_format_instructions()
|
||||
},
|
||||
)
|
||||
|
||||
model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
|
||||
|
||||
chain = template | model | output_parser
|
||||
|
||||
sample = (
|
||||
"Сдайте к пятнице мини-отчёт по LangChain: 2 страницы, упор на агентов. "
|
||||
"Оценка: за полноту и за пример кода."
|
||||
)
|
||||
|
||||
card: AssignmentCard = chain.invoke({"raw_text": sample})
|
||||
|
||||
print("Валидированный объект:")
|
||||
print(card.model_dump())
|
||||
|
||||
print("\nСводка:")
|
||||
print(
|
||||
f"Задание «{card.title}» по теме «{card.subject}». "
|
||||
f"Сдать: {card.deliverable_type}. "
|
||||
f"Дедлайн: {card.deadline_hint or 'не указан'}. "
|
||||
f"Оценивается: {', '.join(card.grading_hints) if card.grading_hints else 'критерии не указаны'}."
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
-90
@@ -1,90 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
from typing import List
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from langchain_core.prompts import PromptTemplate
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_core.output_parsers import PydanticOutputParser
|
||||
|
||||
|
||||
# 1. Модель карточки задания
|
||||
class TaskCard(BaseModel):
|
||||
title: str = Field(..., description="Краткое название задачи")
|
||||
subject: str = Field(..., description="Предмет или область знаний")
|
||||
deadline_hint: str = Field(
|
||||
..., description="Указание срока сдачи в свободной форме"
|
||||
)
|
||||
deliverable_type: str = Field(
|
||||
...,
|
||||
description="Тип сдаваемого материала (отчёт, код, презентация и т.д.)",
|
||||
)
|
||||
grading_hints: List[str] = Field(
|
||||
default_factory=list,
|
||||
description="Ключевые критерии оценки, упомянутые в тексте",
|
||||
)
|
||||
|
||||
|
||||
# 2. Парсер для гарантированного вывода модели
|
||||
parser = PydanticOutputParser(pydantic_object=TaskCard)
|
||||
|
||||
# 3. Шаблон промпта с инструкцией о формате
|
||||
prompt_template = PromptTemplate(
|
||||
template="""
|
||||
Вы — ассистент, который преобразует неформальное описание задания в структурированный объект.
|
||||
Нужно вернуть только данные в следующем формате:
|
||||
|
||||
{format_instructions}
|
||||
|
||||
Текст задания:
|
||||
"{task_text}"
|
||||
""",
|
||||
input_variables=["task_text"],
|
||||
partial_variables={"format_instructions": parser.get_format_instructions()},
|
||||
)
|
||||
|
||||
# 4. Конфигурация LLM
|
||||
llm = ChatOpenAI(
|
||||
temperature=0,
|
||||
model="gpt-3.5-turbo", # можно заменить на любой доступный вариант
|
||||
)
|
||||
|
||||
# 5. Цепочка: промпт → LLM → парсер
|
||||
chain = prompt_template | llm | parser
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) > 1:
|
||||
task_text = " ".join(sys.argv[1:])
|
||||
else:
|
||||
print("Введите описание задания (Ctrl-D для завершения):")
|
||||
task_text = sys.stdin.read().strip()
|
||||
|
||||
if not task_text:
|
||||
print("Пустой ввод. Завершение.")
|
||||
return
|
||||
|
||||
# Запуск цепочки
|
||||
result: TaskCard = chain.invoke({"task_text": task_text})
|
||||
|
||||
# Вывод валидированного объекта
|
||||
print("\n=== Валидированный объект ===")
|
||||
print(result.model_dump(indent=2))
|
||||
|
||||
# Краткая человекочитаемая сводка
|
||||
summary_parts = [
|
||||
f"**Название:** {result.title}",
|
||||
f"**Предмет:** {result.subject}",
|
||||
f"**Срок сдачи:** {result.deadline_hint}",
|
||||
f"**Тип сдаваемого материала:** {result.deliverable_type}",
|
||||
]
|
||||
if result.grading_hints:
|
||||
summary_parts.append(
|
||||
f"**Критерии оценки:** {', '.join(result.grading_hints)}"
|
||||
)
|
||||
print("\n=== Сводка ===")
|
||||
print("\n".join(summary_parts))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user