From fca3de67fae57873aaccf081ee1065ce61b86ff6 Mon Sep 17 00:00:00 2001 From: Damir Date: Tue, 7 Apr 2026 21:36:11 +0300 Subject: [PATCH] update 2 --- main.py | 54 +++++++++++++++++++++++++++++------------------------- run.sh | 16 ++++++++++++++++ ui.py | 53 ++++++++++++++++++++++++++--------------------------- 3 files changed, 71 insertions(+), 52 deletions(-) create mode 100644 run.sh diff --git a/main.py b/main.py index 8f823bd..8057acb 100644 --- a/main.py +++ b/main.py @@ -1,48 +1,52 @@ from fastapi import FastAPI, HTTPException +from pydantic import BaseModel import requests import yaml -from pydantic import BaseModel -app = FastAPI() +app = FastAPI(title="AI CI/CD Assistant") -OLLAMA_URL = "http://10.10.10.136:11434/api/generate" +# ЗАМЕНИТЕ на IP вашего контейнера с Ollama +OLLAMA_API_URL = "http://10.10.10.136:11434/api/generate" -class Prompt(BaseModel): - task_description: str +class GenerationRequest(BaseModel): + description: str + platform: str = "GitHub Actions" # или GitLab CI model: str = "codellama" -def validate_yaml(content: str): +def validate_config(config_text: str): + """Простая валидация YAML синтаксиса""" try: - yaml.safe_load(content) - return True, "Valid YAML" - except yaml.YAMLError as exc: - return False, str(exc) + yaml.safe_load(config_text) + return True, "Success" + except Exception as e: + return False, str(e) -@app.post("/generate_config") -async def generate_config(data: Prompt): +@app.post("/generate") +async def generate_pipeline(req: GenerationRequest): + prompt = f"Write only a valid {req.platform} YAML configuration for: {req.description}. No explanations, just code." + payload = { - "model": data.model, - "prompt": f"Generate only a valid CI/CD YAML configuration for the following task: {data.task_description}. Return ONLY the code block.", + "model": req.model, + "prompt": prompt, "stream": False } - + try: - response = requests.post(OLLAMA_URL, json=payload) - response_data = response.json() - generated_text = response_data.get("response", "") + response = requests.post(OLLAMA_API_URL, json=payload, timeout=60) + raw_text = response.json().get("response", "") - # Очистка от markdown-тегов, если модель их добавила - config_content = generated_text.replace("```yaml", "").replace("```", "").strip() + # Очистка от Markdown-оберток (```yaml ... ```) + clean_code = raw_text.replace("```yaml", "").replace("```", "").strip() - is_valid, message = validate_yaml(config_content) + is_valid, error_msg = validate_config(clean_code) return { - "config": config_content, - "is_valid": is_valid, - "validation_message": message + "status": "ok" if is_valid else "error", + "config": clean_code, + "validation_error": error_msg if not is_valid else None } except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) + raise HTTPException(status_code=500, detail=f"Ollama error: {str(e)}") if __name__ == "__main__": import uvicorn diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..b5cecc9 --- /dev/null +++ b/run.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Активируем виртуальное окружение (если есть) +source venv/bin/activate + +# Запускаем Бэкенд в фоне +echo "Starting Backend..." +python3 app.py > backend.log 2>&1 & + +# Запускаем Фронтенд в фоне +echo "Starting Frontend..." +streamlit run ui.py --server.port 8501 > frontend.log 2>&1 & + +echo "Services are running in background!" +echo "Backend: http://localhost:8000" +echo "Frontend: http://localhost:8501" \ No newline at end of file diff --git a/ui.py b/ui.py index 07131d0..d6976f6 100644 --- a/ui.py +++ b/ui.py @@ -1,39 +1,38 @@ import streamlit as st import requests -st.set_page_config(page_title="AI DevOps Assistant", layout="wide") +st.set_page_config(page_title="DevOps AI Assistant", page_icon="🚀") -st.title("🚀 CI/CD AI Generator & Validator") -st.subheader("Генерация и проверка конфигураций пайплайнов") - -backend_url = "http://localhost:8000/generate_config" +st.title("🤖 AI CI/CD Pipeline Generator") +st.markdown("Прототип сервиса для генерации и валидации конфигураций") with st.sidebar: - st.info("Настройки") - model_name = st.selectbox("Выберите модель Ollama", ["codellama", "llama3", "mistral"]) + st.header("Настройки") + api_url = st.text_input("Backend URL", "http://localhost:8000/generate") + model = st.selectbox("LLM Модель", ["deepseek-r1:1.5b", "qwen2.5-coder:1.5b", "llama3.1:8b", "Arena Model"]) + platform = st.radio("Платформа", ["GitHub Actions", "GitLab CI"]) -task = st.text_area("Опишите задачу (напр. 'Pipeline for Dockerized Node.js app with Jest tests'):") +user_input = st.text_area("Опишите пайплайн (например: 'Python app with pytest and docker build')", height=150) -if st.button("Сгенерировать и проверить"): - if task: - with st.spinner("ИИ формирует конфигурацию..."): - res = requests.post(backend_url, json={"task_description": task, "model": model_name}) - if res.status_code == 200: +if st.button("Сгенерировать конфигурацию", type="primary"): + if user_input: + with st.spinner("LLM думает..."): + try: + res = requests.post(api_url, json={ + "description": user_input, + "platform": platform, + "model": model + }) data = res.json() - col1, col2 = st.columns(2) - - with col1: - st.markdown("### Сгенерированный YAML") + if data["status"] == "ok": + st.success("✅ Конфигурация валидна!") st.code(data["config"], language="yaml") - - with col2: - st.markdown("### Статус валидации") - if data["is_valid"]: - st.success("✅ Конфигурация синтаксически верна") - else: - st.error(f"❌ Ошибка в YAML: {data['validation_message']}") - else: - st.error("Ошибка связи с бекендом") + st.download_button("Скачать .yml", data["config"], file_name="pipeline.yml") + else: + st.error(f"❌ Ошибка валидации: {data['validation_error']}") + st.code(data["config"], language="yaml") + except Exception as e: + st.error(f"Ошибка подключения к бекенду: {e}") else: - st.warning("Введите описание задачи") \ No newline at end of file + st.warning("Пожалуйста, введите описание.") \ No newline at end of file