mal-sh's picture
Use Deepseek-Coder model
c4de5c0 verified
import os
import re
import json
import gradio as gr
from typing import Dict, List, Optional
from openai import OpenAI
# إعداد العميل - يمكنك استخدام أي نموذج متوافق مع OpenAI API
API_KEY = os.getenv("API_KEY", "")
BASE_URL = os.getenv("BASE_URL", "https://api.openai.com/v1")
client = OpenAI(api_key=API_KEY, base_url=BASE_URL) if API_KEY else None
CSS = """
:root { direction: rtl; }
* { font-family: "Tajawal", system-ui, -apple-system, sans-serif; }
.gradio-container { direction: rtl; }
.app-header { text-align: center; margin: 20px 0; }
.app-title { font-size: 24px; font-weight: bold; color: #2D3748; }
.app-sub { color: #718096; margin-bottom: 30px; }
.result-area { direction: ltr; }
"""
SYSTEM_PROMPT = """أنت مساعد متخصص في تحويل أوامر Docker إلى قوالب نشر Ghaymah.
قم بتحليل أوامر Docker Run أو Docker Compose وأنشئ قالب Ghaymah المناسب.
هيكل قالب Ghaymah:
{
"category": "development|automation|database|etc",
"description": "وصف التطبيق",
"icon": "IconName",
"id": "app-id",
"name": "App Name",
"resources": [
{
"type": "volume",
"values": {
"name": "data-volume",
"size": "{{volumeSize}}",
"userId": "{{userId}}"
}
},
{
"type": "app",
"values": {
"container": {
"image": "image:tag"
},
"env": {
"VARIABLE": "value"
},
"name": "app-name",
"ports": [{"expose": true, "number": 8080}],
"projectId": "{{projectId}}",
"publicAccess": {
"baseDomain": "hosted.ghaymah.systems",
"domain": "auto",
"enabled": true
},
"resourceTier": "{{resourceTier}}",
"storage": {
"volumes": [
{
"mountPath": "/data",
"name": "{{resources[0].uniqueName}}"
}
]
}
}
}
],
"variables": {
"resourceTier": {
"default": "t3",
"description": "Instance size",
"options": ["t1", "t2", "t3", "t4", "t5", "t6", "t7"],
"type": "dropdown"
},
"volumeSize": {
"default": "1Gi",
"description": "Volume size",
"options": ["512Mi", "1Gi", "2Gi", "5Gi", "10Gi"],
"type": "dropdown"
}
}
}
Examples
{
"category": "automation",
"description": "n8n workflow automation",
"icon": "Zap",
"id": "n8n",
"name": "n8n",
"resources": [
{
"type": "volume",
"values": {
"name": "n8n-data",
"size": "{{volumeSize}}",
"userId": "{{userId}}"
}
},
{
"type": "app",
"values": {
"container": {
"image": "docker.n8n.io/n8nio/n8n"
},
"env": {
"EXECUTIONS_DATA_MAX_AGE": "336",
"EXECUTIONS_DATA_PRUNE": "true",
"N8N_EDITOR_BASE_URL": "https://{{resources[1].uniqueName}}.hosted.ghaymah.systems",
"N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS": false,
"N8N_HIRING_BANNER_ENABLED": false,
"N8N_HOST": "{{resources[1].uniqueName}}.hosted.ghaymah.systems",
"N8N_PORT": "5678",
"N8N_PROTOCOL": "https",
"N8N_PROXY_HOPS": 1,
"N8N_TEMPLATES_ENABLED": true,
"WEBHOOK_URL": "https://{{resources[1].uniqueName}}.hosted.ghaymah.systems"
},
"fsGroup": 1000,
"name": "n8n",
"ports": [
{
"expose": true,
"number": 5678
}
],
"projectId": "{{projectId}}",
"publicAccess": {
"baseDomain": "hosted.ghaymah.systems",
"domain": "auto",
"enabled": true
},
"resourceTier": "{{resourceTier}}",
"storage": {
"volumes": [
{
"mountPath": "/home/node",
"name": "{{resources[0].uniqueName}}"
}
]
}
}
}
],
"variables": {
"resourceTier": {
"default": "t4",
"description": "Instance size",
"options": [
"t1",
"t2",
"t3",
"t4",
"t5",
"t6",
"t7"
],
"type": "dropdown"
},
"volumeSize": {
"default": "1Gi",
"description": "Volume size",
"options": [
"512Mi",
"1Gi",
"2Gi",
"5Gi",
"10Gi"
],
"type": "dropdown"
}
}
}
Example 2
{
"category": "development",
"description": "DocuSeal is an open-source document signing platform",
"icon": "Box",
"id": "docuseal",
"name": "DocuSeal",
"resources": [
{
"type": "volume",
"values": {
"name": "docuseal-data",
"size": "{{volumeSize}}",
"userId": "{{userId}}"
}
},
{
"type": "volume",
"values": {
"name": "postgres-data",
"size": "{{pgVolumeSize}}",
"userId": "{{userId}}"
}
},
{
"type": "app",
"values": {
"container": {
"image": "docuseal/docuseal:latest"
},
"env": {
"DATABASE_URL": "postgresql://postgres:postgres@{{resources[1].uniqueName}}:5432/docuseal",
"FORCE_SSL": "{{host}}"
},
"name": "docuseal",
"ports": [
{
"expose": true,
"number": 3000
}
],
"projectId": "{{projectId}}",
"publicAccess": {
"baseDomain": "hosted.ghaymah.systems",
"domain": "auto",
"enabled": true
},
"resourceTier": "{{resourceTier}}",
"storage": {
"volumes": [
{
"mountPath": "/data/docuseal",
"name": "{{resources[0].uniqueName}}"
}
]
}
}
},
{
"type": "app",
"values": {
"container": {
"image": "postgres:16"
},
"env": {
"PGDATA": "/var/lib/postgresql/data/pgdata",
"POSTGRES_DB": "docuseal",
"POSTGRES_PASSWORD": "postgres",
"POSTGRES_USER": "postgres"
},
"healthCheck": {
"command": [
"CMD-SHELL",
"pg_isready -U postgres"
],
"interval": 5,
"retries": 5,
"timeout": 5
},
"name": "postgres",
"ports": [
{
"expose": false,
"number": 5432
}
],
"projectId": "{{projectId}}",
"publicAccess": {
"enabled": false
},
"resourceTier": "{{resourceTier}}",
"storage": {
"volumes": [
{
"mountPath": "/var/lib/postgresql/data",
"name": "{{resources[1].uniqueName}}"
}
]
}
}
}
],
"variables": {
"host": {
"default": "",
"description": "Host domain for SSL (leave empty if not using SSL)",
"type": "text"
},
"pgVolumeSize": {
"default": "1Gi",
"description": "PostgreSQL data volume size",
"options": [
"512Mi",
"1Gi",
"2Gi",
"5Gi",
"10Gi"
],
"type": "dropdown"
},
"resourceTier": {
"default": "t3",
"description": "Instance size",
"options": [
"t1",
"t2",
"t3",
"t4",
"t5",
"t6",
"t7"
],
"type": "dropdown"
},
"volumeSize": {
"default": "2Gi",
"description": "DocuSeal data volume size",
"options": [
"512Mi",
"1Gi",
"2Gi",
"5Gi",
"10Gi"
],
"type": "dropdown"
}
}
}
Example 3
{
"category": "database",
"description": "PostgreSQL database server with Hasura GraphQL Engine",
"icon": "Database",
"id": "postgres-hasura",
"name": "Hasura GraphQL",
"resources": [
{
"type": "volume",
"values": {
"name": "postgres-data",
"size": "{{volumeSize}}",
"userId": "{{userId}}"
}
},
{
"type": "app",
"values": {
"container": {
"image": "postgres:{{version}}"
},
"env": {
"PGDATA": "/var/lib/postgresql/data/pgdata",
"POSTGRES_DB": "graphql",
"POSTGRES_HOST_AUTH_METHOD": "scram-sha-256",
"POSTGRES_INITDB_ARGS": "--auth-host=scram-sha-256 --auth-local=scram-sha-256",
"POSTGRES_PASSWORD": "postgres",
"POSTGRES_USER": "postgres"
},
"fsGroup": 999,
"name": "postgres",
"ports": [
{
"expose": false,
"number": 5432
}
],
"projectId": "{{projectId}}",
"publicAccess": {
"enabled": false
},
"resourceTier": "{{resourceTier}}",
"storage": {
"volumes": [
{
"mountPath": "/var/lib/postgresql/data",
"name": "{{resources[0].uniqueName}}"
}
]
}
}
},
{
"type": "app",
"values": {
"container": {
"image": "hasura/graphql-engine:latest"
},
"env": {
"HASURA_GRAPHQL_ADMIN_SECRET": "{{adminSecret}}",
"HASURA_GRAPHQL_DATABASE_URL": "postgres://postgres:postgres@{{resources[1].uniqueName}}:5432/graphql",
"HASURA_GRAPHQL_DEV_MODE": "true",
"HASURA_GRAPHQL_ENABLED_LOG_TYPES": "startup, http-log, webhook-log, websocket-log, query-log",
"HASURA_GRAPHQL_ENABLE_CONSOLE": "true"
},
"name": "hasura",
"ports": [
{
"expose": true,
"number": 8080
}
],
"projectId": "{{projectId}}",
"publicAccess": {
"baseDomain": "hosted.ghaymah.systems",
"domain": "auto",
"enabled": true
},
"resourceTier": "{{hasuraResourceTier}}"
}
}
],
"variables": {
"adminSecret": {
"default": "test-secret",
"description": "Hasura admin secret",
"type": "password"
},
"hasuraResourceTier": {
"default": "t3",
"description": "Hasura instance size",
"options": [
"t1",
"t2",
"t3",
"t4",
"t5",
"t6",
"t7"
],
"type": "dropdown"
},
"resourceTier": {
"default": "t3",
"description": "PostgreSQL instance size",
"options": [
"t1",
"t2",
"t3",
"t4",
"t5",
"t6",
"t7"
],
"type": "dropdown"
},
"version": {
"default": "15",
"description": "PostgreSQL version (compatible with Hasura)",
"options": [
"12",
"13",
"14",
"15",
"16"
],
"type": "dropdown"
},
"volumeSize": {
"default": "200Mi",
"description": "Volume size for database storage",
"options": [
"200Mi",
"500Mi",
"1Gi",
"2Gi",
"5Gi",
"10Gi"
],
"type": "dropdown"
}
}
}
أرجع JSON صالح فقط بدون أي نص إضافي."""
def analyze_docker_command(command: str) -> str:
"""تحليل أمر Docker باستخدام النموذج اللغوي"""
if not client:
return json.dumps({
"error": "⚠️ لم يتم تكوين API_KEY. الرجاء إضافة المفتاح في متغيرات البيئة."
}, indent=2, ensure_ascii=False)
try:
response = client.chat.completions.create(
model="DeepSeek-Coder",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": f"""حول أمر Docker التالي إلى قالب Ghaymah:
{command}
ملاحظات:
- استخدم المنافذ المناسبة
- أضف المتغيرات البيئية اللازمة
- حدد الفئة المناسبة (development, automation, database, etc)
- اختر أيقونة مناسبة من: Box, Database, Server, Code, Zap, Search
- تأكد من أن القالب يعمل بشكل صحيح على منصة Ghaymah"""}
],
temperature=0.1,
max_tokens=2000
)
result = response.choices[0].message.content
# محاولة استخراج JSON من الرد
json_match = re.search(r'\{.*\}', result, re.DOTALL)
if json_match:
return json_match.group()
else:
return result
except Exception as e:
return json.dumps({
"error": f"فشل في التحليل: {str(e)}"
}, indent=2, ensure_ascii=False)
def validate_and_format_json(json_str: str) -> str:
"""التحقق من صحة JSON وتنسيقه"""
try:
parsed = json.loads(json_str)
return json.dumps(parsed, indent=2, ensure_ascii=False)
except json.JSONDecodeError:
# إذا لم يكن JSON صالحاً، إرجاعه كما هو مع رسالة خطأ
return f"⚠️ الناتج ليس JSON صالح:\n\n{json_str}"
def process_docker_input(docker_input: str, input_type: str) -> dict:
"""معالجة إدخال Docker وإرجاع قالب Ghaymah"""
if not docker_input.strip():
return {"error": "الرجاء إدخال أمر Docker أو تكوين Docker Compose"}
try:
if input_type == "docker_run":
result = analyze_docker_command(docker_input)
else: # docker_compose
result = analyze_docker_command(f"docker-compose:\n{docker_input}")
# محاولة تحويل الناتج إلى قاموس
try:
if isinstance(result, str):
return json.loads(result)
return result
except:
return {"raw_output": result}
except Exception as e:
return {"error": f"حدث خطأ: {str(e)}"}
# أمثلة للاستخدام
DOCKER_RUN_EXAMPLES = [
"docker run -d --name nginx -p 8080:80 nginx:latest",
"docker run -it --rm -p 7700:7700 -v $(pwd)/meili_data:/meili_data getmeili/meilisearch:v1.16",
"docker run -d --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=mysecretpassword -v pg_data:/var/lib/postgresql/data postgres:15",
"docker run -d --name redis -p 6379:6379 -v redis_data:/data redis:7-alpine"
]
DOCKER_COMPOSE_EXAMPLES = [
"""version: '3.8'
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
db:
image: postgres:15
environment:
POSTGRES_PASSWORD: mysecretpassword
volumes:
- pg_data:/var/lib/postgresql/data
volumes:
pg_data:""",
"""version: '3'
services:
app:
image: node:18
ports:
- "3000:3000"
environment:
- NODE_ENV=production
volumes:
- app_data:/app/data
volumes:
app_data:"""
]
# واجهة Gradio
with gr.Blocks(title="محول Docker إلى Ghaymah", css=CSS, theme=gr.themes.Soft()) as demo:
gr.HTML("""
<div class="app-header">
<div class="app-title">🔄 محول Docker إلى Ghaymah</div>
<div class="app-sub">حوّل أوامر Docker Run و Docker Compose إلى قوالب نشر Ghaymah تلقائياً</div>
</div>
""")
with gr.Row():
with gr.Column(scale=1):
input_type = gr.Radio(
choices=["docker_run", "docker_compose"],
value="docker_run",
label="نوع الإدخال",
info="اختر نوع أمر Docker الذي تريد تحويله"
)
gr.Markdown("### أمثلة جاهزة")
with gr.Tab("Docker Run"):
docker_run_examples = gr.Dataset(
components=[gr.Textbox(visible=False)],
samples=[[ex] for ex in DOCKER_RUN_EXAMPLES],
label="اختر مثالاً"
)
with gr.Tab("Docker Compose"):
docker_compose_examples = gr.Dataset(
components=[gr.Textbox(visible=False)],
samples=[[ex] for ex in DOCKER_COMPOSE_EXAMPLES],
label="اختر مثالاً"
)
gr.Markdown("""
### 💡 نصائح للاستخدام:
- أدخل أمر `docker run` كاملاً أو تكوين `docker-compose.yml`
- سيقوم النموذج اللغوي بتحليل الأوامر وإنشاء القالب المناسب
- يمكنك تعديل القالب الناتج حسب احتياجاتك
""")
with gr.Column(scale=2):
docker_input = gr.Textbox(
label="أمر Docker أو تكوين Docker Compose",
placeholder="أدخل أمر docker run هنا... أو تكوين docker-compose...",
lines=8,
max_lines=15
)
convert_btn = gr.Button("تحويل إلى قالب Ghaymah 🚀", variant="primary")
output = gr.JSON(
label="قالب Ghaymah الناتج"
)
# معالجة الأمثلة
def load_example(example):
return example[0]
docker_run_examples.click(load_example, docker_run_examples, docker_input)
docker_compose_examples.click(load_example, docker_compose_examples, docker_input)
# زر التحويل
convert_btn.click(
fn=process_docker_input,
inputs=[docker_input, input_type],
outputs=output
)
# أيضًا السماح بالإدخال باستخدام Enter
docker_input.submit(
fn=process_docker_input,
inputs=[docker_input, input_type],
outputs=output
)
if __name__ == "__main__":
demo.launch(share=True)