Spaces:
Build error
Build error
Commit ·
94c52e3
1
Parent(s): fbfa58f
synth app updated
Browse files- app.py +1 -1
- translator/agent.py +6 -4
- translator/examples/Rotator.cs +8 -0
- translator/llm_client.py +17 -23
- translator/synth.py +42 -31
- translator/synth_blueprint.py +20 -0
- translator/synth_cpp.py +25 -0
app.py
CHANGED
|
@@ -17,7 +17,7 @@ iface = gr.Interface(
|
|
| 17 |
inputs=[
|
| 18 |
gr.Textbox(lines=20, label="Unity C# code"),
|
| 19 |
gr.Radio(["cpp", "blueprint", "both"], value="both", label="Target"),
|
| 20 |
-
gr.Radio(["
|
| 21 |
],
|
| 22 |
outputs=[
|
| 23 |
gr.Textbox(lines=20, label="Unreal C++ (.h/.cpp)"),
|
|
|
|
| 17 |
inputs=[
|
| 18 |
gr.Textbox(lines=20, label="Unity C# code"),
|
| 19 |
gr.Radio(["cpp", "blueprint", "both"], value="both", label="Target"),
|
| 20 |
+
gr.Radio(["hf", "openai"], value="hf", label="Model backend")
|
| 21 |
],
|
| 22 |
outputs=[
|
| 23 |
gr.Textbox(lines=20, label="Unreal C++ (.h/.cpp)"),
|
translator/agent.py
CHANGED
|
@@ -6,12 +6,14 @@ class TranslationAgent:
|
|
| 6 |
def __init__(self, mapping_path="mapping_table.json"):
|
| 7 |
self.mapping = load_mapping(mapping_path)
|
| 8 |
|
| 9 |
-
def translate(self, csharp_code: str, target_format="both",
|
| 10 |
parsed = parse_csharp(csharp_code)
|
| 11 |
results = {"cpp": "", "blueprint_py": ""}
|
|
|
|
| 12 |
if target_format in ("cpp", "both"):
|
| 13 |
-
results["cpp"] = synthesize_cpp(parsed, self.mapping)
|
|
|
|
| 14 |
if target_format in ("blueprint", "both"):
|
| 15 |
-
results["blueprint_py"] = synthesize_blueprint_python(parsed, self.mapping)
|
| 16 |
-
|
| 17 |
return results["cpp"], results["blueprint_py"]
|
|
|
|
| 6 |
def __init__(self, mapping_path="mapping_table.json"):
|
| 7 |
self.mapping = load_mapping(mapping_path)
|
| 8 |
|
| 9 |
+
def translate(self, csharp_code: str, target_format="both", backend="hf"):
|
| 10 |
parsed = parse_csharp(csharp_code)
|
| 11 |
results = {"cpp": "", "blueprint_py": ""}
|
| 12 |
+
|
| 13 |
if target_format in ("cpp", "both"):
|
| 14 |
+
results["cpp"] = synthesize_cpp(parsed, self.mapping, backend=backend)
|
| 15 |
+
|
| 16 |
if target_format in ("blueprint", "both"):
|
| 17 |
+
results["blueprint_py"] = synthesize_blueprint_python(parsed, self.mapping, backend=backend)
|
| 18 |
+
|
| 19 |
return results["cpp"], results["blueprint_py"]
|
translator/examples/Rotator.cs
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
using UnityEngine;
|
| 2 |
+
|
| 3 |
+
public class Rotator : MonoBehaviour {
|
| 4 |
+
public float speed = 90f;
|
| 5 |
+
void Update() {
|
| 6 |
+
transform.Rotate(0, speed * Time.deltaTime, 0);
|
| 7 |
+
}
|
| 8 |
+
}
|
translator/llm_client.py
CHANGED
|
@@ -1,28 +1,22 @@
|
|
| 1 |
-
import os, json
|
| 2 |
from huggingface_hub import InferenceClient
|
|
|
|
|
|
|
| 3 |
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
client = InferenceClient(token=token) if token else InferenceClient() # will use unauth if possible
|
| 7 |
-
# Use chat-like API where available; else use text generation
|
| 8 |
-
response = client.text_generation(model=model, inputs=prompt, max_new_tokens=max_new_tokens)
|
| 9 |
-
# client.text_generation returns structured result; pick the text
|
| 10 |
-
if isinstance(response, list):
|
| 11 |
-
return response[0].get("generated_text", "")
|
| 12 |
-
elif isinstance(response, dict) and "generated_text" in response:
|
| 13 |
-
return response["generated_text"]
|
| 14 |
-
else:
|
| 15 |
-
# fallback stringify
|
| 16 |
-
return json.dumps(response)
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
| 23 |
model=model,
|
| 24 |
-
messages=[
|
| 25 |
-
|
| 26 |
-
|
|
|
|
| 27 |
)
|
| 28 |
-
return
|
|
|
|
|
|
|
| 1 |
from huggingface_hub import InferenceClient
|
| 2 |
+
from openai import OpenAI
|
| 3 |
+
import os
|
| 4 |
|
| 5 |
+
HF_MODEL_DEFAULT = "mistralai/Mixtral-8x7B-Instruct"
|
| 6 |
+
OPENAI_MODEL_DEFAULT = "gpt-4o-mini"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
+
def generate_with_hf(prompt, model=HF_MODEL_DEFAULT):
|
| 9 |
+
client = InferenceClient(model=model, token=os.getenv("HF_TOKEN"))
|
| 10 |
+
response = client.text_generation(prompt, max_new_tokens=1024)
|
| 11 |
+
return response
|
| 12 |
+
|
| 13 |
+
def generate_with_openai(prompt, model=OPENAI_MODEL_DEFAULT):
|
| 14 |
+
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
| 15 |
+
completion = client.chat.completions.create(
|
| 16 |
model=model,
|
| 17 |
+
messages=[
|
| 18 |
+
{"role": "system", "content": "You are a Unity→Unreal translation expert."},
|
| 19 |
+
{"role": "user", "content": prompt},
|
| 20 |
+
],
|
| 21 |
)
|
| 22 |
+
return completion.choices[0].message.content
|
translator/synth.py
CHANGED
|
@@ -1,33 +1,44 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
"""
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
"""
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
Generate two files separated with markers:
|
| 11 |
-
---FILE: MyActor.h---
|
| 12 |
-
[contents]
|
| 13 |
-
---FILE: MyActor.cpp---
|
| 14 |
-
[contents]
|
| 15 |
-
|
| 16 |
-
Be concise and compile-focused. Use UPROPERTY / UFUNCTION where appropriate.
|
| 17 |
-
"""
|
| 18 |
-
from .llm_client import generate_with_hf
|
| 19 |
-
return generate_with_hf(prompt, model="gpt-4o-mini")
|
| 20 |
-
|
| 21 |
-
def synthesize_blueprint_python(parsed: dict, mapping: dict) -> str:
|
| 22 |
-
prompt = f"""Given this parsed Unity class and mapping rules, produce a Python Editor script (uses unreal python API)
|
| 23 |
-
that will create a Blueprint Actor class in /Game/Blueprints named BP_<ClassName> with:
|
| 24 |
-
- a StaticMeshComponent as root
|
| 25 |
-
- a float property RotationSpeed exposed to Blueprints
|
| 26 |
-
- a Tick override that rotates actor by RotationSpeed * DeltaTime
|
| 27 |
-
|
| 28 |
-
Provide the Python file only.
|
| 29 |
-
Parsed: {parsed}
|
| 30 |
-
Mapping: {mapping}
|
| 31 |
-
"""
|
| 32 |
-
from .llm_client import generate_with_hf
|
| 33 |
-
return generate_with_hf(prompt, model="gpt-4o-mini")
|
|
|
|
| 1 |
+
from .llm_client import generate_with_hf, generate_with_openai
|
| 2 |
+
|
| 3 |
+
def synthesize_cpp(parsed: dict, mapping: dict, backend: str = "hf", prompt_context: str = "") -> str:
|
| 4 |
+
"""
|
| 5 |
+
Converts Unity C# parsed structure into Unreal Engine C++ (header + source).
|
| 6 |
+
"""
|
| 7 |
+
prompt = f"""
|
| 8 |
+
Translate the following Unity C# class to idiomatic Unreal Engine C++ (header and source).
|
| 9 |
+
Mapping rules: {mapping}
|
| 10 |
+
Parsed structure: {parsed}
|
| 11 |
+
|
| 12 |
+
Generate two files separated with markers:
|
| 13 |
+
---FILE: MyActor.h---
|
| 14 |
+
[contents]
|
| 15 |
+
---FILE: MyActor.cpp---
|
| 16 |
+
[contents]
|
| 17 |
+
|
| 18 |
+
Be concise, compile-ready, and use UPROPERTY/UFUNCTION macros where suitable.
|
| 19 |
+
{prompt_context}
|
| 20 |
"""
|
| 21 |
+
|
| 22 |
+
if backend == "hf":
|
| 23 |
+
return generate_with_hf(prompt)
|
| 24 |
+
else:
|
| 25 |
+
return generate_with_openai(prompt)
|
| 26 |
+
|
| 27 |
+
def synthesize_blueprint_python(parsed: dict, mapping: dict, backend: str = "hf") -> str:
|
| 28 |
+
prompt = f"""
|
| 29 |
+
Given this parsed Unity class and mapping rules, produce a Python Editor script using Unreal's Python API
|
| 30 |
+
that will create a Blueprint Actor in /Game/Blueprints named BP_<ClassName> with:
|
| 31 |
+
- A StaticMeshComponent as root
|
| 32 |
+
- A float property 'RotationSpeed' exposed to Blueprints
|
| 33 |
+
- A Tick override that rotates actor by RotationSpeed * DeltaTime
|
| 34 |
+
|
| 35 |
+
Provide only the Python file content.
|
| 36 |
+
|
| 37 |
+
Parsed: {parsed}
|
| 38 |
+
Mapping: {mapping}
|
| 39 |
"""
|
| 40 |
+
|
| 41 |
+
if backend == "hf":
|
| 42 |
+
return generate_with_hf(prompt)
|
| 43 |
+
else:
|
| 44 |
+
return generate_with_openai(prompt)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
translator/synth_blueprint.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .llm_client import generate_with_hf, generate_with_openai
|
| 2 |
+
|
| 3 |
+
def synthesize_blueprint_python(parsed: dict, mapping: dict, backend: str = "hf") -> str:
|
| 4 |
+
prompt = f"""
|
| 5 |
+
Given this parsed Unity class and mapping rules, produce a Python Editor script using Unreal's Python API
|
| 6 |
+
that will create a Blueprint Actor in /Game/Blueprints named BP_<ClassName> with:
|
| 7 |
+
- A StaticMeshComponent as root
|
| 8 |
+
- A float property 'RotationSpeed' exposed to Blueprints
|
| 9 |
+
- A Tick override that rotates actor by RotationSpeed * DeltaTime
|
| 10 |
+
|
| 11 |
+
Provide only the Python file content.
|
| 12 |
+
|
| 13 |
+
Parsed: {parsed}
|
| 14 |
+
Mapping: {mapping}
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
if backend == "hf":
|
| 18 |
+
return generate_with_hf(prompt)
|
| 19 |
+
else:
|
| 20 |
+
return generate_with_openai(prompt)
|
translator/synth_cpp.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .llm_client import generate_with_hf, generate_with_openai
|
| 2 |
+
|
| 3 |
+
def synthesize_cpp(parsed: dict, mapping: dict, backend: str = "hf", prompt_context: str = "") -> str:
|
| 4 |
+
"""
|
| 5 |
+
Converts Unity C# parsed structure into Unreal Engine C++ (header + source).
|
| 6 |
+
"""
|
| 7 |
+
prompt = f"""
|
| 8 |
+
Translate the following Unity C# class to idiomatic Unreal Engine C++ (header and source).
|
| 9 |
+
Mapping rules: {mapping}
|
| 10 |
+
Parsed structure: {parsed}
|
| 11 |
+
|
| 12 |
+
Generate two files separated with markers:
|
| 13 |
+
---FILE: MyActor.h---
|
| 14 |
+
[contents]
|
| 15 |
+
---FILE: MyActor.cpp---
|
| 16 |
+
[contents]
|
| 17 |
+
|
| 18 |
+
Be concise, compile-ready, and use UPROPERTY/UFUNCTION macros where suitable.
|
| 19 |
+
{prompt_context}
|
| 20 |
+
"""
|
| 21 |
+
|
| 22 |
+
if backend == "hf":
|
| 23 |
+
return generate_with_hf(prompt)
|
| 24 |
+
else:
|
| 25 |
+
return generate_with_openai(prompt)
|