diagram / utils.py
ivanm151's picture
qwen new promt 1
1833177
from pydantic import BaseModel
import re
class DiagramRequest(BaseModel):
description: str
class DiagramResponse(BaseModel):
plantuml_code: str
def preprocess_description(desc: str) -> str:
"""
Улучшенный препроцессинг:
- Убираем лишние пустые строки в начале/конце
- Нормализуем множественные пробелы и табы
- Сохраняем \n внутри — это важно для таблиц "Шаг | Роль" и списков
- Убираем только trailing/leading whitespace
"""
# Удаляем BOM, если есть
desc = desc.strip().lstrip('\ufeff')
# Заменяем множественные пробелы/табы на один, но сохраняем строки
desc = re.sub(r'[ \t]+', ' ', desc)
# Убираем пустые строки в начале и конце, но оставляем внутри
lines = [line.rstrip() for line in desc.splitlines() if line.strip()]
desc = '\n'.join(lines).strip()
return desc
def get_prompt(description: str) -> list[dict]:
"""
Возвращает список сообщений в формате ChatML для Qwen2.5-Instruct.
Это сильно улучшает качество по сравнению с plain text.
"""
system_prompt = """You are an expert PlantUML diagram generator. Your ONLY task is to convert the given process description into a valid, complete PlantUML activity diagram.
Rules you MUST follow strictly:
- Always output ONLY the PlantUML code: from @startuml to @enduml inclusive.
- NEVER add explanations, comments, markdown, extra text, apologies or anything else.
- Use the new activity diagram syntax (beta).
- Use swimlanes/partitions (|Actor|) for different roles or actors when mentioned (Шаг | Роль, Actor: action, etc.).
- Use start / stop / (*) / (*) for begin/end.
- Use :action; for steps.
- Use if (Condition?) then (yes) ... else (no) ... endif for decisions.
- Use -> [label]; for arrows with conditions if needed.
- Make diagrams clean, logical and complete — close all branches, ifs, etc.
- Detect type: simple sequence → linear; table Шаг/Роль → swimlanes; branches (Найдена?, Автоматически?) → if/else.
Examples follow. Follow their style and completeness exactly."""
messages = [
{"role": "system", "content": system_prompt},
]
# Few-shot примеры (полные, без '...', валидные)
examples = [
# Пример 1: Таблица с ролями (тех. стек)
{
"user": """Шаг | Роль
1. Создание запроса | Инициатор
2. Внесение технологии в тех. стек в статусе "Consideration" | Координатор
3. Оценка по техническим критериям | Инициатор
4. Уточнение требований к технологии | Совет по технологиям, Координатор, Владелец продукта
5. Оценка ограничений и рисков принятия новой мажорной версии | Координатор
6. Презентация новой мажорной версии | Инициатор
7. Принятие решения | Главный корпоративный архитектор, Совет по технологиям
8. Внесение записи в тех. стек, оповещение | Координатор
9. Перевод прошлой мажорной версии в статус Deprecated | Координатор
10. Оповещение | Координатор
11. Планирование обновления продукта | Координатор
12. Планирование автоматизации ресурсов | Координатор
13. Изменение атрибутов технологии в стеке | Координатор""",
"assistant": """@startuml
skinparam shadowing false
skinparam monochrome true
|Инициатор|
start
:Создание запроса;
|Координатор|
:Внесение технологии в тех. стек (Consideration);
|Инициатор|
:Оценка по техническим критериям;
|Совет по технологиям, Координатор, Владелец продукта|
:Уточнение требований к технологии;
|Координатор|
:Оценка ограничений и рисков;
|Инициатор|
:Презентация новой мажорной версии;
|Главный корпоративный архитектор, Совет по технологиям|
:Принятие решения;
|Координатор|
:Внесение записи в тех. стек;
:Оповещение;
:Перевод прошлой версии в Deprecated;
:Оповещение;
:Планирование обновления продукта;
:Планирование автоматизации ресурсов;
:Изменение атрибутов технологии;
stop
@enduml"""
},
# Пример 2: Ещё одна таблица с ролями
{
"user": """Шаг | Роль
1. Создание запроса | Инициатор
2. Подтверждение потребности в изменении условий использования | Координатор
3. Определение пользователей технологии | Совет по технологиям
4. Оценка трудозатрат | Совет по технологиям
5. Принятие решения | Главный корпоративный архитектор, Совет по технологиям
6. Изменение статуса технологии | Координатор
7. Оповещение клиентов | Команда разработки
8. Выполнение работ | ДЭиС""",
"assistant": """@startuml
skinparam shadowing false
|Инициатор|
start
:Создание запроса;
|Координатор|
:Подтверждение потребности в изменении;
|Совет по технологиям|
:Определение пользователей технологии;
:Оценка трудозатрат;
|Главный корпоративный архитектор, Совет по технологиям|
:Принятие решения;
|Координатор|
:Изменение статуса технологии;
|Команда разработки|
:Оповещение клиентов;
|ДЭиС|
:Выполнение работ;
stop
@enduml"""
},
# Пример 3: Простая последовательность без ролей
{
"user": """Шаг
1. Создание запроса
2. Рассмотрение запроса
3. Анализ запроса
4. Принятие решения о реализации изменения
5. Реализация улучшений и исправление несоответствий
6. Оценка результатов""",
"assistant": """@startuml
start
:Создание запроса;
:Рассмотрение запроса;
:Анализ запроса;
:Принятие решения о реализации;
:Реализация улучшений и исправлений;
:Оценка результатов;
stop
@enduml"""
},
# Пример 4: Чайник с событием и ветвлением
{
"user": """Шаг
1. Начало
2. Наполнить чайник
3. Включить чайник
4. Ждать закипания
5. Событие: Чайник закипел
6. Таймер: 30 секунд
7. Автовыключение
8. Ручное выключение
9. Чай готов""",
"assistant": """@startuml
start
:Наполнить чайник;
:Включить чайник;
:Ждать закипания;
note right: Событие: Чайник закипел
:Таймер: 30 секунд;
if (Выключен автоматически?) then (да)
:Автовыключение;
else (нет)
:Ручное выключение;
endif
:Чай готов;
stop
@enduml"""
},
# Пример 5: Решение с ветвлением (работа/учёба)
{
"user": """Шаг
1. Зачисление
2. Обновить резюме
3. Искать гибкую работу
4. Решение: Найдена?
5. Договориться о графике
6. Совмещение работы и учебы
7. Фокус на учебе
8. Только учеба""",
"assistant": """@startuml
start
:Зачисление;
:Обновить резюме;
:Искать гибкую работу;
if (Работа найдена?) then (да)
:Договориться о графике;
:Совмещение работы и учебы;
else (нет)
:Фокус на учебе;
:Только учеба;
endif
stop
@enduml"""
},
]
# Добавляем все few-shot
for ex in examples:
messages.append({"role": "user", "content": ex["user"]})
messages.append({"role": "assistant", "content": ex["assistant"]})
# Финальный запрос
messages.append(
{"role": "user", "content": f"Generate PlantUML activity diagram for this description:\n\n{description}"})
return messages