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