تبدیل کد بین زبانهای برنامهنویسی با هوش مصنوعی؛ ساخت AI Code Translator
در این آموزش یاد میگیرید کد را بدون تغییر ناخواسته رفتار بین زبانها تبدیل کنید و یک AI Code Translator بسازید که قرارداد، تست و تفاوتهای معنایی Python و JavaScript را کنترل میکند.
تبدیل کد بین زبانهای برنامهنویسی با هوش مصنوعی؛ از Python تا JavaScript
تبدیل چند خط کد از یک زبان برنامهنویسی به زبان دیگر ساده به نظر میرسد. کافی است کد Python را به یک مدل هوش مصنوعی بدهیم و بگوییم:
این کد را به JavaScript تبدیل کن.
مدل نیز در چند ثانیه نسخهای شبیه کد مقصد تولید میکند. اما در پروژههای واقعی، شباهت ظاهری کد به معنی یکسانبودن رفتار نیست.
زبانهای برنامهنویسی در جزئیات مهمی با یکدیگر تفاوت دارند:
- نوع عدد و دقت محاسبات
- رفتار Integer و Float
- مقدارهای
null،Noneوundefined - Truthiness
- مقایسه مساوی
- نحوه گردکردن
- مدیریت تاریخ و Timezone
- ترتیب Propertyهای Object
- رفتار Exception
- Async و Promise
- Unicode و طول رشته
- Regex Dialect
- Serialization
- Overflow
- Mutable و Immutable بودن دادهها
- کتابخانه استاندارد
- سیستم Type
- مدیریت Dependency
بنابراین تبدیل کد با هوش مصنوعی نباید فقط «ترجمه Syntax» باشد. هدف اصلی باید حفظ Contract و رفتار قابل مشاهده نرمافزار باشد.
در این مقاله یک پروژه واقعی میسازیم که:
- یک تابع قیمتگذاری را در Python تعریف میکند.
- رفتار آن را با Specification مستقل ثبت میکند.
- Test Fixtureهای مشترک میسازد.
- با API درواره برنامه مهاجرت تولید میکند.
- نسخه JavaScript را با هوش مصنوعی میسازد.
- خروجی Python و JavaScript را روی دادههای یکسان اجرا میکند.
- اختلاف رفتاری دو نسخه را پیدا میکند.
- نتیجه را فقط در صورت عبور از تستها قابل قبول میداند.
AI Code Translator چیست؟
AI Code Translator ابزاری است که Source Code یک زبان را دریافت و نسخهای معادل در زبان مقصد تولید میکند.
ورودی:
def clamp(value, minimum, maximum):
return max(minimum, min(value, maximum))
خروجی JavaScript:
export function clamp(value, minimum, maximum) {
return Math.max(minimum, Math.min(value, maximum));
}
این نمونه ساده است، اما تبدیل یک ماژول واقعی به اطلاعات بیشتری نیاز دارد:
- زبان و نسخه مبدأ
- زبان و نسخه مقصد
- Runtime مقصد
- Specification
- API عمومی
- Typeها
- Dependencyها
- Test Suite
- اثرهای جانبی
- محدودیتهای عملکرد
- رفتار خطا
- قرارداد Serialization
- ساختار فایل مقصد
تفاوت ترجمه کد، رفکتور و بازنویسی
ترجمه یا Code Translation
رفتار موجود در یک زبان دیگر پیادهسازی میشود.
Python → JavaScript
PHP → Python
Java → Kotlin
C# → TypeScript
رفکتور
زبان و رفتار عمومی حفظ میشوند، اما ساختار داخلی بهبود مییابد.
Python قدیمی → Python خواناتر
بازنویسی
پیادهسازی جدید ممکن است معماری، Dependency و رفتار متفاوتی داشته باشد.
برنامه قدیمی PHP → سرویسهای جدید TypeScript
تبدیل بین دو زبان معمولاً به بازنویسی نزدیکتر از Refactor است، زیرا تفاوتهای معنایی زبان مقصد میتواند رفتار را تغییر دهد.
هوش مصنوعی در تبدیل کد چه کمکی میکند؟
تبدیل Syntax
- تعریف تابع
- کلاس
- شرط
- حلقه
- Collection
- Import
- Exception
- Async Function
نگاشت کتابخانه استاندارد
برای مثال:
json.dumps(data)
ممکن است به این تبدیل شود:
JSON.stringify(data)
تبدیل Typeها
list[str]
به TypeScript:
string[]
ساخت تست مقصد
مدل میتواند Test Suite معادل برای Runtime مقصد تولید کند.
شناسایی تفاوتهای معنایی
یک مدل مناسب میتواند هشدار دهد که Decimal در Python معادل مستقیم Number در JavaScript نیست.
تولید Migration Plan
قبل از تولید کد، ماژولها، Dependencyها و ترتیب مهاجرت را مشخص میکند.
توضیح بخشهای نیازمند تصمیم
برای مثال:
در نسخه Python، Dictionary با کلید ناموجود KeyError ایجاد میکند.
در JavaScript، دسترسی به Property ناموجود undefined برمیگرداند.
رفتار مقصد باید صریحاً مشخص شود.
چه چیزهایی را نباید به مدل واگذار کنیم؟
مدل نباید تنها مرجع این تصمیمها باشد:
- آیا رفتار قدیمی صحیح است؟
- کدام خطا باید حفظ شود؟
- آیا دقت عددی قابل کاهش است؟
- آیا تغییر API مجاز است؟
- آیا Dependency جدید قابل قبول است؟
- آیا ترتیب Side Effectها قابل تغییر است؟
- آیا نتیجه Migration آماده انتشار است؟
- آیا تستهای موجود پوشش کافی دارند؟
مدل پیشنویس و تحلیل تولید میکند؛ Test Suite و Specification درباره صحت نتیجه تصمیم میگیرند.
مهمترین تفاوتهای Python و JavaScript
None، null و undefined
Python:
value = None
JavaScript:
const value = null;
اما JavaScript مقدار undefined نیز دارد. تبدیل خودکار این دو مقدار ممکن است Contract JSON را تغییر دهد.
تقسیم عدد صحیح
Python:
5 // 2
نتیجه:
2
JavaScript:
5 / 2
نتیجه:
2.5
معادل نزدیکتر برای اعداد مثبت:
Math.floor(5 / 2);
اما رفتار floor برای عدد منفی نیز باید بررسی شود.
دقت عددی
Python از Integer با دقت دلخواه پشتیبانی میکند. Number در JavaScript محدودیت دقت عدد صحیح دارد.
Number.MAX_SAFE_INTEGER
برای عددهای بزرگ ممکن است به BigInt نیاز باشد.
مقادیر Truthy و Falsy
Python:
bool([])
نتیجه:
False
JavaScript:
Boolean([])
نتیجه:
true
تبدیل مستقیم شرطها میتواند رفتار را تغییر دهد.
مقایسه
Python:
1 == True
نتیجه True است.
JavaScript:
1 === true
نتیجه false است.
در JavaScript باید تا حد امکان از مقایسه صریح و Typeهای مشخص استفاده شود.
رشته و Unicode
در Python، len تعداد Code Pointها را در بسیاری از حالتهای رایج نشان میدهد. در JavaScript، length تعداد UTF-16 Code Unitها را برمیگرداند.
برای بعضی Emojiها:
"😀".length
نتیجه:
2
این تفاوت در Validation طول رشته مهم است.
Dictionary و Object
Python Dictionary میتواند انواع مختلفی از کلیدها داشته باشد. Object در JavaScript عمدتاً کلیدهای String یا Symbol دارد. برای برخی کاربردها Map معادل مناسبتری است.
Exception
Python:
raise ValueError("invalid page")
JavaScript:
throw new RangeError("invalid page");
نوع و متن خطا باید در Contract تعریف شوند.
Async
Python:
result = await service.fetch()
JavaScript:
const result = await service.fetch();
شباهت Syntax به معنی یکسانبودن مدیریت Task، Cancellation، Timeout و Event Loop نیست.
فرایند صحیح تبدیل کد با AI
مرحله اول: Inventory
مشخص کنید چه چیزی باید مهاجرت کند:
- فایلها
- ماژولها
- API عمومی
- CLI
- Dependencyها
- تستها
- Configuration
- ورودی و خروجی
- فرمت فایل
- اثرهای جانبی
مرحله دوم: تعریف Contract
برای هر تابع یا Endpoint:
- ورودی
- خروجی
- نوع داده
- Validation
- Exception
- Edge Case
- Side Effect
- ترتیب عملیات
مرحله سوم: Test Baseline
تمام تستهای نسخه مبدأ باید اجرا شوند. وضعیت فعلی باید مشخص باشد.
مرحله چهارم: Fixture مشترک
دادههای ورودی و خروجی مرجع در JSON ذخیره شوند تا هر دو Runtime از همان Fixture استفاده کنند.
مرحله پنجم: Migration Plan
مدل فقط برنامه تبدیل را تولید کند؛ هنوز کد ساخته نشود.
مرحله ششم: تبدیل یک ماژول
تبدیل باید مرحلهای باشد، نه کل Repository در یک درخواست.
مرحله هفتم: اجرای تست مقصد
کد مقصد Compile یا Parse و سپس تست شود.
مرحله هشتم: Differential Testing
نسخه مبدأ و مقصد روی ورودی یکسان اجرا و خروجی مقایسه شوند.
مرحله نهم: بررسی انسانی
تفاوتهای معنایی، Dependency و خوانایی بررسی شوند.
پروژه عملی: تبدیل موتور محاسبه قیمت از Python به JavaScript
در این پروژه تمام مبلغها در کوچکترین واحد پول بهصورت Integer نگهداری میشوند. برای مثال اگر واحد سیستم ریال باشد، مقدار 1250000 دقیقاً یک عدد صحیح است.
نرخ تخفیف و مالیات نیز با Basis Point تعریف میشوند:
10000 basis points = 100%
1000 basis points = 10%
900 basis points = 9%
این طراحی از بسیاری از اختلافهای Float میان Python و JavaScript جلوگیری میکند.
Specification پروژه
فایل specifications/pricing.md:
# Pricing contract
## Input
تابع calculate_order_total این ورودیها را میگیرد:
- items: فهرستی از Itemها
- discount_bps: نرخ تخفیف بر حسب Basis Point
- tax_bps: نرخ مالیات بر حسب Basis Point
هر Item:
- sku: رشته غیرخالی
- unit_price: عدد صحیح غیرمنفی
- quantity: عدد صحیح غیرمنفی
## Validation
- items باید Array یا List باشد.
- discount_bps باید عدد صحیح بین 0 و 10000 باشد.
- tax_bps باید عدد صحیح بین 0 و 10000 باشد.
- unit_price و quantity باید عدد صحیح غیرمنفی باشند.
- sku باید رشته غیرخالی باشد.
## Calculation
- subtotal مجموع unit_price ضربدر quantity است.
- discount از subtotal محاسبه میشود.
- taxable_amount برابر subtotal منهای discount است.
- tax از taxable_amount محاسبه میشود.
- total برابر taxable_amount بهعلاوه tax است.
- تقسیم نسبتها با روش Round Half Up انجام میشود.
## Output
خروجی شامل عددهای صحیح زیر است:
- subtotal
- discount
- taxable_amount
- tax
- total
## Compatibility
نسخه Python و JavaScript باید برای Fixtureهای مشترک خروجی یکسان یا خطای معادل تولید کنند.
ایجاد پروژه
mkdir ai-code-translator
cd ai-code-translator
python -m venv .venv
فعالسازی در Linux و macOS:
source .venv/bin/activate
فعالسازی در Windows:
.venv\Scripts\Activate.ps1
نصب وابستگیها:
pip install \
openai \
python-dotenv \
pydantic \
pytest
ساخت پوشهها:
mkdir \
source_python \
target_javascript \
tests_python \
tests_javascript \
fixtures \
translator \
specifications \
plans \
output
فایلهای اصلی:
source_python/pricing.py
target_javascript/pricing.mjs
tests_python/test_pricing.py
tests_javascript/pricing.test.mjs
fixtures/pricing-cases.json
translator/__init__.py
translator/schemas.py
translator/collector.py
translator/planner.py
translator/generator.py
translator/validator.py
translator/renderer.py
plan_translation.py
generate_translation.py
compare_runtimes.py
پیادهسازی مبدأ در Python
فایل source_python/pricing.py:
from dataclasses import dataclass
BASIS_POINT_DENOMINATOR = 10_000
@dataclass(frozen=True)
class Item:
sku: str
unit_price: int
quantity: int
def round_ratio(
value: int,
numerator: int,
denominator: int,
) -> int:
return (
value * numerator
+ denominator // 2
) // denominator
def validate_rate(
value: int,
name: str,
) -> None:
if not isinstance(value, int):
raise TypeError(
f"{name} must be an integer"
)
if value < 0 or value > 10_000:
raise ValueError(
f"{name} must be between "
f"0 and 10000"
)
def validate_item(
item: Item,
) -> None:
if not isinstance(item.sku, str):
raise TypeError(
"sku must be a string"
)
if not item.sku:
raise ValueError(
"sku cannot be empty"
)
if not isinstance(
item.unit_price,
int,
):
raise TypeError(
"unit_price must be an integer"
)
if item.unit_price < 0:
raise ValueError(
"unit_price cannot be negative"
)
if not isinstance(
item.quantity,
int,
):
raise TypeError(
"quantity must be an integer"
)
if item.quantity < 0:
raise ValueError(
"quantity cannot be negative"
)
def calculate_order_total(
items: list[Item],
discount_bps: int = 0,
tax_bps: int = 0,
) -> dict[str, int]:
if not isinstance(items, list):
raise TypeError(
"items must be a list"
)
validate_rate(
discount_bps,
"discount_bps",
)
validate_rate(
tax_bps,
"tax_bps",
)
subtotal = 0
for item in items:
validate_item(item)
subtotal += (
item.unit_price
* item.quantity
)
discount = round_ratio(
subtotal,
discount_bps,
BASIS_POINT_DENOMINATOR,
)
taxable_amount = (
subtotal - discount
)
tax = round_ratio(
taxable_amount,
tax_bps,
BASIS_POINT_DENOMINATOR,
)
total = taxable_amount + tax
return {
"subtotal": subtotal,
"discount": discount,
"taxable_amount": (
taxable_amount
),
"tax": tax,
"total": total,
}
Test Fixture مشترک
فایل fixtures/pricing-cases.json:
[
{
"name": "empty order",
"input": {
"items": [],
"discount_bps": 0,
"tax_bps": 0
},
"expected": {
"subtotal": 0,
"discount": 0,
"taxable_amount": 0,
"tax": 0,
"total": 0
}
},
{
"name": "one item without discount or tax",
"input": {
"items": [
{
"sku": "A",
"unit_price": 10000,
"quantity": 2
}
],
"discount_bps": 0,
"tax_bps": 0
},
"expected": {
"subtotal": 20000,
"discount": 0,
"taxable_amount": 20000,
"tax": 0,
"total": 20000
}
},
{
"name": "discount before tax",
"input": {
"items": [
{
"sku": "A",
"unit_price": 10000,
"quantity": 1
}
],
"discount_bps": 1000,
"tax_bps": 2000
},
"expected": {
"subtotal": 10000,
"discount": 1000,
"taxable_amount": 9000,
"tax": 1800,
"total": 10800
}
},
{
"name": "round half up",
"input": {
"items": [
{
"sku": "A",
"unit_price": 5,
"quantity": 1
}
],
"discount_bps": 1000,
"tax_bps": 0
},
"expected": {
"subtotal": 5,
"discount": 1,
"taxable_amount": 4,
"tax": 0,
"total": 4
}
},
{
"name": "multiple items",
"input": {
"items": [
{
"sku": "A",
"unit_price": 1250,
"quantity": 3
},
{
"sku": "B",
"unit_price": 980,
"quantity": 2
}
],
"discount_bps": 500,
"tax_bps": 900
},
"expected": {
"subtotal": 5710,
"discount": 286,
"taxable_amount": 5424,
"tax": 488,
"total": 5912
}
}
]
در مورد آخر:
Subtotal = 3750 + 1960 = 5710
Discount = 5710 × 500 / 10000 = 285.5 → 286
Taxable = 5710 - 286 = 5424
Tax = 5424 × 900 / 10000 = 488.16 → 488
Total = 5424 + 488 = 5912
فرمولها بهصورت متن ساده نوشته شدهاند تا با Ghost سازگار باشند.
تست نسخه Python
فایل tests_python/test_pricing.py:
import json
from pathlib import Path
import pytest
from source_python.pricing import (
Item,
calculate_order_total,
)
CASES = json.loads(
Path(
"fixtures/pricing-cases.json"
).read_text(encoding="utf-8")
)
@pytest.mark.parametrize(
"case",
CASES,
ids=[
case["name"]
for case in CASES
],
)
def test_pricing_cases(case):
items = [
Item(**item)
for item in (
case["input"]["items"]
)
]
result = calculate_order_total(
items,
discount_bps=(
case["input"][
"discount_bps"
]
),
tax_bps=(
case["input"]["tax_bps"]
),
)
assert result == case["expected"]
@pytest.mark.parametrize(
"discount_bps",
[
-1,
10001,
],
)
def test_rejects_invalid_discount(
discount_bps,
):
with pytest.raises(ValueError):
calculate_order_total(
[],
discount_bps=discount_bps,
)
def test_rejects_empty_sku():
with pytest.raises(
ValueError,
match="sku cannot be empty",
):
calculate_order_total(
[
Item(
sku="",
unit_price=100,
quantity=1,
)
]
)
اجرای تست:
pytest -q tests_python
قبل از مهاجرت، تستهای نسخه مبدأ باید موفق باشند.
تعریف Schema برنامه مهاجرت
فایل translator/schemas.py:
from typing import Literal
from pydantic import BaseModel, Field
class SemanticDifference(BaseModel):
topic: str
source_behavior: str
target_risk: str
required_strategy: str
verification: str
class DependencyMapping(BaseModel):
source_dependency: str
target_dependency: str | None = None
strategy: Literal[
"standard_library",
"third_party",
"custom_implementation",
"not_required",
"unresolved",
]
notes: str
class MigrationStep(BaseModel):
order: int
title: str
source_files: list[str]
target_files: list[str]
goal: str
preserved_contracts: list[str]
tests_to_run: list[str]
completion_criteria: list[str]
risk: Literal[
"high",
"medium",
"low",
]
class TranslationPlan(BaseModel):
source_language: str
source_version: str
target_language: str
target_runtime: str
public_api: list[str]
behavior_contracts: list[str]
semantic_differences: list[
SemanticDifference
]
dependency_mapping: list[
DependencyMapping
]
steps: list[MigrationStep]
out_of_scope: list[str]
unresolved_questions: list[str]
class GeneratedFile(BaseModel):
path: str
language: str
content: str
purpose: str
class TranslationOutput(BaseModel):
summary: str
generated_files: list[
GeneratedFile
]
preserved_behaviors: list[str]
known_differences: list[str]
assumptions: list[str]
validation_commands: list[str]
جمعآوری Context مهاجرت
فایل translator/collector.py:
import platform
import subprocess
import sys
from pathlib import Path
def read_file(
file_path: Path,
max_chars: int = 60_000,
) -> str:
content = file_path.read_text(
encoding="utf-8"
)
if len(content) > max_chars:
return (
content[:max_chars]
+ "\n\n[CONTENT TRUNCATED]"
)
return content
def run_python_tests() -> dict:
command = [
sys.executable,
"-m",
"pytest",
"-q",
"tests_python",
]
result = subprocess.run(
command,
capture_output=True,
text=True,
timeout=60,
check=False,
)
return {
"command": command,
"return_code": result.returncode,
"stdout": result.stdout[-10_000:],
"stderr": result.stderr[-5_000:],
}
def collect_translation_context() -> dict:
return {
"source_language": "Python",
"source_version": (
sys.version.split()[0]
),
"target_language": (
"JavaScript ESM"
),
"target_runtime": (
"Node.js 20 or newer"
),
"source_files": {
"source_python/pricing.py": (
read_file(
Path(
"source_python/"
"pricing.py"
)
)
)
},
"specification": read_file(
Path(
"specifications/pricing.md"
)
),
"python_tests": read_file(
Path(
"tests_python/"
"test_pricing.py"
)
),
"shared_fixtures": read_file(
Path(
"fixtures/"
"pricing-cases.json"
)
),
"test_baseline": (
run_python_tests()
),
"constraints": [
"Use only Node.js standard library.",
"Generate ECMAScript modules.",
"Do not add npm dependencies.",
"Keep all monetary values as integers.",
"Reject unsafe JavaScript integers.",
"Preserve calculation order.",
"Preserve error messages where practical.",
"Do not change the shared fixture format.",
],
"environment": {
"platform": platform.platform(),
},
}
تولید Migration Plan با API درواره
فایل translator/planner.py:
import json
import os
from dotenv import load_dotenv
from openai import OpenAI
from pydantic import ValidationError
from translator.schemas import (
TranslationPlan,
)
load_dotenv()
api_key = os.getenv("DARVAREH_API_KEY")
model = os.getenv("DARVAREH_MODEL")
if not api_key:
raise RuntimeError(
"DARVAREH_API_KEY is not configured."
)
if not model:
raise RuntimeError(
"DARVAREH_MODEL is not configured."
)
client = OpenAI(
api_key=api_key,
base_url="https://api.darvareh.ir/v1",
)
SYSTEM_PROMPT = """
تو یک مهندس ارشد مهاجرت نرمافزار هستی.
در این مرحله فقط Migration Plan تولید کن و کد مقصد نساز.
قواعد:
- Specification منبع رفتار مورد انتظار است.
- Source Code منبع رفتار فعلی است.
- تفاوت معنایی Python و JavaScript را صریح ثبت کن.
- Syntax مشابه را معادل رفتاری قطعی فرض نکن.
- برنامه را مرحلهای و قابل تست بساز.
- Dependency جدید پیشنهاد نده مگر در Constraint مجاز باشد.
- تمام مبلغها باید Integer باقی بمانند.
- رفتار Round Half Up باید حفظ شود.
- خروجی فقط JSON معتبر باشد.
"""
OUTPUT_TEMPLATE = {
"source_language": "Python",
"source_version": "3.12",
"target_language": "JavaScript ESM",
"target_runtime": "Node.js 20+",
"public_api": [
"calculateOrderTotal"
],
"behavior_contracts": [
"string"
],
"semantic_differences": [
{
"topic": "integer precision",
"source_behavior": "string",
"target_risk": "string",
"required_strategy": "string",
"verification": "string",
}
],
"dependency_mapping": [],
"steps": [
{
"order": 1,
"title": "string",
"source_files": [
"source_python/pricing.py"
],
"target_files": [
"target_javascript/pricing.mjs"
],
"goal": "string",
"preserved_contracts": [
"string"
],
"tests_to_run": [
"node --test tests_javascript"
],
"completion_criteria": [
"string"
],
"risk": "medium",
}
],
"out_of_scope": [],
"unresolved_questions": [],
}
def generate_translation_plan(
context: dict,
) -> TranslationPlan:
response = client.chat.completions.create(
model=model,
temperature=0.1,
messages=[
{
"role": "system",
"content": SYSTEM_PROMPT,
},
{
"role": "user",
"content": (
"Context مهاجرت:\n\n"
+ json.dumps(
context,
ensure_ascii=False,
indent=2,
)
+ "\n\nقالب خروجی:\n"
+ json.dumps(
OUTPUT_TEMPLATE,
ensure_ascii=False,
indent=2,
)
),
},
],
)
raw_output = (
response.choices[0]
.message.content
)
if not raw_output:
raise RuntimeError(
"The model returned an "
"empty migration plan."
)
try:
parsed = json.loads(raw_output)
except json.JSONDecodeError as error:
raise RuntimeError(
f"Invalid JSON from model: "
f"{error}"
) from error
try:
return TranslationPlan.model_validate(
parsed
)
except ValidationError as error:
raise RuntimeError(
f"Migration plan validation "
f"failed: {error}"
) from error
ساخت برنامه مهاجرت
فایل plan_translation.py:
from pathlib import Path
from translator.collector import (
collect_translation_context,
)
from translator.planner import (
generate_translation_plan,
)
def main():
context = (
collect_translation_context()
)
if (
context["test_baseline"][
"return_code"
]
!= 0
):
raise RuntimeError(
"Python baseline tests must pass "
"before translation."
)
plan = generate_translation_plan(
context
)
output_path = Path(
"plans/translation-plan.json"
)
output_path.parent.mkdir(
parents=True,
exist_ok=True,
)
output_path.write_text(
plan.model_dump_json(indent=2),
encoding="utf-8",
)
print(plan.model_dump_json(indent=2))
print(f"\nPlan saved to {output_path}")
if __name__ == "__main__":
main()
فایل .env:
DARVAREH_API_KEY=YOUR_API_KEY
DARVAREH_MODEL=MODEL_ID_DARVAREH
اجرا:
python plan_translation.py
برای دریافت API Key در درواره ثبتنام کنید. Model ID را از صفحه مدلهای درواره بردارید.
تولید کد مقصد
فایل translator/generator.py:
import json
from pathlib import Path
from translator.planner import (
client,
model,
)
from translator.schemas import (
TranslationOutput,
TranslationPlan,
)
SYSTEM_PROMPT = """
تو فقط کد مقصد و تست مقصد را بر اساس Plan تأییدشده تولید میکنی.
قواعد:
- فقط فایلهای مجاز Plan را تولید کن.
- از JavaScript ESM و Node.js standard library استفاده کن.
- Dependency خارجی اضافه نکن.
- از Number فقط با کنترل Number.isSafeInteger استفاده کن.
- تمام مبلغها Integer باقی بمانند.
- Round Half Up نسخه Python را حفظ کن.
- Fixture مشترک را تغییر نده.
- تستها از node:test و node:assert/strict استفاده کنند.
- API عمومی calculateOrderTotal باشد.
- Feature جدید اضافه نکن.
- خروجی فقط JSON معتبر باشد.
"""
OUTPUT_TEMPLATE = {
"summary": "string",
"generated_files": [
{
"path": (
"target_javascript/"
"pricing.mjs"
),
"language": "javascript",
"content": "string",
"purpose": "string",
},
{
"path": (
"tests_javascript/"
"pricing.test.mjs"
),
"language": "javascript",
"content": "string",
"purpose": "string",
},
],
"preserved_behaviors": [
"string"
],
"known_differences": [],
"assumptions": [],
"validation_commands": [
"node --check target_javascript/pricing.mjs",
"node --test tests_javascript/pricing.test.mjs"
],
}
def generate_translation() -> TranslationOutput:
plan = TranslationPlan.model_validate_json(
Path(
"plans/translation-plan.json"
).read_text(encoding="utf-8")
)
payload = {
"plan": plan.model_dump(),
"source": Path(
"source_python/pricing.py"
).read_text(encoding="utf-8"),
"specification": Path(
"specifications/pricing.md"
).read_text(encoding="utf-8"),
"python_tests": Path(
"tests_python/test_pricing.py"
).read_text(encoding="utf-8"),
"shared_fixtures": Path(
"fixtures/pricing-cases.json"
).read_text(encoding="utf-8"),
}
response = client.chat.completions.create(
model=model,
temperature=0,
messages=[
{
"role": "system",
"content": SYSTEM_PROMPT,
},
{
"role": "user",
"content": (
json.dumps(
payload,
ensure_ascii=False,
indent=2,
)
+ "\n\nقالب خروجی:\n"
+ json.dumps(
OUTPUT_TEMPLATE,
ensure_ascii=False,
indent=2,
)
),
},
],
)
raw_output = (
response.choices[0]
.message.content
)
if not raw_output:
raise RuntimeError(
"The model returned no "
"translated files."
)
return TranslationOutput.model_validate(
json.loads(raw_output)
)
اعتبارسنجی مسیر فایلها
فایل translator/validator.py:
from pathlib import Path
from translator.schemas import (
TranslationOutput,
)
ALLOWED_OUTPUT_FILES = {
"target_javascript/pricing.mjs",
"tests_javascript/pricing.test.mjs",
}
class TranslationValidationError(
ValueError
):
pass
def validate_generated_files(
output: TranslationOutput,
) -> None:
generated_paths = {
generated_file.path
for generated_file
in output.generated_files
}
unknown_paths = (
generated_paths
- ALLOWED_OUTPUT_FILES
)
if unknown_paths:
raise TranslationValidationError(
"Unexpected generated files: "
+ ", ".join(
sorted(unknown_paths)
)
)
missing_paths = (
ALLOWED_OUTPUT_FILES
- generated_paths
)
if missing_paths:
raise TranslationValidationError(
"Required files were not "
"generated: "
+ ", ".join(
sorted(missing_paths)
)
)
for generated_file in (
output.generated_files
):
path = Path(
generated_file.path
)
if ".." in path.parts:
raise TranslationValidationError(
"Invalid output path."
)
ذخیره فایلهای تولیدشده
فایل generate_translation.py:
from pathlib import Path
from translator.generator import (
generate_translation,
)
from translator.validator import (
validate_generated_files,
)
def main():
output = generate_translation()
validate_generated_files(
output
)
for generated_file in (
output.generated_files
):
output_path = Path(
generated_file.path
)
output_path.parent.mkdir(
parents=True,
exist_ok=True,
)
output_path.write_text(
generated_file.content,
encoding="utf-8",
)
print(
f"Generated {output_path}"
)
metadata_path = Path(
"output/translation-result.json"
)
metadata_path.parent.mkdir(
parents=True,
exist_ok=True,
)
metadata_path.write_text(
output.model_dump_json(indent=2),
encoding="utf-8",
)
if __name__ == "__main__":
main()
اجرا:
python generate_translation.py
فایلهای تولیدشده باید پیش از اجرا بررسی شوند.
نسخه JavaScript مورد انتظار
فایل target_javascript/pricing.mjs باید ساختاری نزدیک به این داشته باشد:
const BASIS_POINT_DENOMINATOR = 10_000;
function assertSafeInteger(value, name) {
if (!Number.isSafeInteger(value)) {
throw new TypeError(
`${name} must be a safe integer`,
);
}
}
function roundRatio(
value,
numerator,
denominator,
) {
assertSafeInteger(value, "value");
assertSafeInteger(
numerator,
"numerator",
);
assertSafeInteger(
denominator,
"denominator",
);
const multiplied = value * numerator;
if (!Number.isSafeInteger(multiplied)) {
throw new RangeError(
"calculation exceeds safe integer range",
);
}
return Math.floor(
(
multiplied
+ Math.floor(denominator / 2)
)
/ denominator,
);
}
function validateRate(value, name) {
assertSafeInteger(value, name);
if (value < 0 || value > 10_000) {
throw new RangeError(
`${name} must be between 0 and 10000`,
);
}
}
function validateItem(item) {
if (
typeof item !== "object"
|| item === null
|| Array.isArray(item)
) {
throw new TypeError(
"item must be an object",
);
}
if (typeof item.sku !== "string") {
throw new TypeError(
"sku must be a string",
);
}
if (item.sku.length === 0) {
throw new RangeError(
"sku cannot be empty",
);
}
assertSafeInteger(
item.unit_price,
"unit_price",
);
if (item.unit_price < 0) {
throw new RangeError(
"unit_price cannot be negative",
);
}
assertSafeInteger(
item.quantity,
"quantity",
);
if (item.quantity < 0) {
throw new RangeError(
"quantity cannot be negative",
);
}
}
export function calculateOrderTotal(
items,
discountBps = 0,
taxBps = 0,
) {
if (!Array.isArray(items)) {
throw new TypeError(
"items must be an array",
);
}
validateRate(
discountBps,
"discount_bps",
);
validateRate(
taxBps,
"tax_bps",
);
let subtotal = 0;
for (const item of items) {
validateItem(item);
const lineTotal = (
item.unit_price
* item.quantity
);
if (!Number.isSafeInteger(lineTotal)) {
throw new RangeError(
"line total exceeds safe integer range",
);
}
subtotal += lineTotal;
if (!Number.isSafeInteger(subtotal)) {
throw new RangeError(
"subtotal exceeds safe integer range",
);
}
}
const discount = roundRatio(
subtotal,
discountBps,
BASIS_POINT_DENOMINATOR,
);
const taxableAmount = (
subtotal - discount
);
const tax = roundRatio(
taxableAmount,
taxBps,
BASIS_POINT_DENOMINATOR,
);
const total = taxableAmount + tax;
if (!Number.isSafeInteger(total)) {
throw new RangeError(
"total exceeds safe integer range",
);
}
return {
subtotal,
discount,
taxable_amount: taxableAmount,
tax,
total,
};
}
نکته مهم: نسخه JavaScript برای اعداد بزرگتر از محدوده Safe Integer خطا میدهد. نسخه Python چنین محدودیتی ندارد. این یک تفاوت شناختهشده است که باید در Migration Report ثبت شود یا با BigInt حل شود.
تست JavaScript با Node.js
فایل tests_javascript/pricing.test.mjs:
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import test from "node:test";
import {
calculateOrderTotal,
} from "../target_javascript/pricing.mjs";
const fixtureUrl = new URL(
"../fixtures/pricing-cases.json",
import.meta.url,
);
const cases = JSON.parse(
await readFile(
fixtureUrl,
"utf8",
),
);
for (const caseItem of cases) {
test(caseItem.name, () => {
const input = caseItem.input;
const result = calculateOrderTotal(
input.items,
input.discount_bps,
input.tax_bps,
);
assert.deepEqual(
result,
caseItem.expected,
);
});
}
test(
"rejects an empty sku",
() => {
assert.throws(
() => calculateOrderTotal(
[
{
sku: "",
unit_price: 100,
quantity: 1,
},
],
),
/sku cannot be empty/,
);
},
);
test(
"rejects an invalid discount rate",
() => {
assert.throws(
() => calculateOrderTotal(
[],
10_001,
0,
),
/discount_bps must be between/,
);
},
);
بررسی Syntax و اجرای تست مقصد
بررسی Syntax:
node --check target_javascript/pricing.mjs
اجرای تست:
node --test tests_javascript/pricing.test.mjs
قبولی تست مقصد لازم است، اما هنوز برای اثبات کامل همارزی کافی نیست.
Differential Testing میان Python و JavaScript
هدف این است که هر دو نسخه روی ورودی یکسان اجرا شوند و خروجیهایشان مقایسه شود.
Runner نسخه Python
فایل source_python/run_case.py:
import json
import sys
from source_python.pricing import (
Item,
calculate_order_total,
)
def main():
payload = json.loads(
sys.stdin.read()
)
try:
items = [
Item(**item)
for item in payload["items"]
]
result = calculate_order_total(
items,
discount_bps=payload.get(
"discount_bps",
0,
),
tax_bps=payload.get(
"tax_bps",
0,
),
)
output = {
"ok": True,
"result": result,
"error": None,
}
except Exception as error:
output = {
"ok": False,
"result": None,
"error": {
"type": (
type(error).__name__
),
"message": str(error),
},
}
print(
json.dumps(
output,
ensure_ascii=False,
)
)
if __name__ == "__main__":
main()
Runner نسخه JavaScript
فایل target_javascript/run-case.mjs:
import {
calculateOrderTotal,
} from "./pricing.mjs";
let input = "";
for await (const chunk of process.stdin) {
input += chunk;
}
const payload = JSON.parse(input);
let output;
try {
const result = calculateOrderTotal(
payload.items,
payload.discount_bps ?? 0,
payload.tax_bps ?? 0,
);
output = {
ok: true,
result,
error: null,
};
} catch (error) {
output = {
ok: false,
result: null,
error: {
type: error.constructor.name,
message: error.message,
},
};
}
process.stdout.write(
JSON.stringify(output),
);
اسکریپت مقایسه Runtimeها
فایل compare_runtimes.py:
import json
import subprocess
import sys
from pathlib import Path
FIXTURES = json.loads(
Path(
"fixtures/pricing-cases.json"
).read_text(encoding="utf-8")
)
def run_process(
command: list[str],
payload: dict,
) -> dict:
result = subprocess.run(
command,
input=json.dumps(payload),
capture_output=True,
text=True,
timeout=10,
check=False,
)
if result.returncode != 0:
raise RuntimeError(
result.stderr.strip()
or "Runtime process failed."
)
return json.loads(
result.stdout
)
def main():
differences = []
for case in FIXTURES:
payload = case["input"]
python_output = run_process(
[
sys.executable,
"-m",
"source_python.run_case",
],
payload,
)
javascript_output = run_process(
[
"node",
"target_javascript/"
"run-case.mjs",
],
payload,
)
if (
python_output
!= javascript_output
):
differences.append(
{
"case": case["name"],
"python": python_output,
"javascript": (
javascript_output
),
}
)
if differences:
print(
json.dumps(
differences,
ensure_ascii=False,
indent=2,
)
)
raise SystemExit(1)
print(
f"All {len(FIXTURES)} cases "
"matched across runtimes."
)
if __name__ == "__main__":
main()
اجرا:
python compare_runtimes.py
خروجی موفق:
All 5 cases matched across runtimes.
مقایسه Exceptionها
نوع Exception میان زبانها یکسان نیست:
| Python | JavaScript |
|---|---|
TypeError | TypeError |
ValueError | معمولاً RangeError یا Error |
KeyError | رفتار مستقیم مشابه ندارد |
IndexError | ممکن است undefined دریافت شود |
بنابراین مقایسه مستقیم نام Exception همیشه مناسب نیست. بهتر است یک Error Contract زبانخنثی تعریف کنید:
{
"code": "INVALID_RATE",
"message": "discount_bps must be between 0 and 10000"
}
سپس هر Runtime Exception داخلی خود را به این قرارداد تبدیل کند.
Error Contract مشترک
Python:
class PricingError(ValueError):
def __init__(
self,
code: str,
message: str,
):
super().__init__(message)
self.code = code
JavaScript:
export class PricingError extends Error {
constructor(code, message) {
super(message);
this.name = "PricingError";
this.code = code;
}
}
این تغییر اگر در API عمومی ظاهر شود باید جداگانه و با تصمیم روشن انجام شود.
تولید تستهای بیشتر با Property-based Testing
Fixtureهای ثابت همه حالتها را پوشش نمیدهند.
در Python میتوان از Hypothesis استفاده کرد:
pip install hypothesis
نمونه تولید Case:
from hypothesis import (
given,
strategies as st,
)
@given(
unit_price=st.integers(
min_value=0,
max_value=1_000_000,
),
quantity=st.integers(
min_value=0,
max_value=100,
),
discount_bps=st.integers(
min_value=0,
max_value=10_000,
),
tax_bps=st.integers(
min_value=0,
max_value=10_000,
),
)
def test_generated_case(
unit_price,
quantity,
discount_bps,
tax_bps,
):
...
میتوان این ورودیها را در فایل JSON ثبت و هر دو Runtime را با آنها اجرا کرد.
تفاوت Round در Python و JavaScript
Python:
round(2.5)
از Banker's Rounding استفاده میکند و ممکن است نتیجه 2 باشد.
JavaScript:
Math.round(2.5)
نتیجه 3 است.
به همین دلیل در پروژه ما الگوریتم Round Half Up را با حساب Integer بهصورت صریح پیادهسازی کردیم:
rounded = floor(
(value × numerator + denominator / 2)
/ denominator
)
هر تفاوت گردکردن میتواند در مبالغ انباشته اثر زیادی ایجاد کند.
تبدیل Decimal از Python
اگر Source از Decimal استفاده میکند، سه راه کلی وجود دارد:
Integer Minor Unit
مبالغ در کوچکترین واحد پول نگهداری شوند. برای بسیاری از سیستمها انتخاب مناسبی است.
BigInt
برای عددهای صحیح بزرگ:
const amount = 1250000n;
اما BigInt مستقیماً در JSON Serialize نمیشود و به قرارداد جدا نیاز دارد.
کتابخانه Decimal
یک Dependency مقصد برای Decimal Arithmetic استفاده شود. انتخاب کتابخانه باید آگاهانه و متناسب با پروژه باشد.
تبدیل مستقیم به Number بدون بررسی دقت مناسب نیست.
تبدیل Date و Time
Python:
datetime.now(timezone.utc)
JavaScript:
new Date()
هر دو میتوانند لحظه فعلی را نشان دهند، اما تفاوتهایی در Parse، Formatting و Timezone دارند.
روش مناسب:
- تبادل زمان با ISO 8601
- ذخیره زمان مرجع به UTC
- ثبت Timezone ورودی
- تست تاریخهای مرزی
- Parse با روش مشخص
- اجتناب از رشته تاریخ مبهم
نمونههای مبهم:
01/02/2026
ممکن است اول فوریه یا دوم ژانویه تفسیر شود.
تبدیل Regex میان زبانها
Python:
(?P<year>[0-9]{4})
JavaScript:
(?<year>[0-9]{4})
Flagها و برخی قابلیتها نیز متفاوتاند. هر Pattern باید در Runtime مقصد Compile و روی Test Case مشترک اجرا شود.
تبدیل Async Code
Python:
async def load_user(user_id):
return await repository.get(user_id)
JavaScript:
export async function loadUser(userId) {
return await repository.get(userId);
}
اما باید این موارد بررسی شوند:
- نوع Promise
- مدیریت Reject
- Timeout
- Cancellation
- ترتیب اجرای Taskها
- Parallelism
- Cleanup
- Connection Lifecycle
حذف await در JavaScript همیشه بهینهسازی بیخطر نیست؛ ممکن است محل ثبت Stack Trace یا مدیریت خطا را تغییر دهد.
تبدیل Class و Dataclass
Python:
@dataclass(frozen=True)
class Product:
id: int
name: str
JavaScript ساده:
export class Product {
constructor(id, name) {
this.id = id;
this.name = name;
Object.freeze(this);
}
}
TypeScript:
export interface Product {
readonly id: number;
readonly name: string;
}
انتخاب Class یا Object یا Interface باید بر اساس نحوه استفاده از Type انجام شود.
تبدیل Python Dictionary Comprehension
Python:
result = {
item.id: item.name
for item in items
}
JavaScript با Object:
const result = Object.fromEntries(
items.map((item) => [
item.id,
item.name,
]),
);
اگر کلیدها غیررشتهای یا ترتیب خاص مهم باشد، Map ممکن است مناسبتر باشد.
تبدیل Generator
Python:
def iter_active(users):
for user in users:
if user.active:
yield user
JavaScript:
export function* iterActive(users) {
for (const user of users) {
if (user.active) {
yield user;
}
}
}
مدل باید Lazy بودن رفتار را حفظ کند و آن را بیدلیل به Array کامل تبدیل نکند.
تبدیل API Backend
برای مهاجرت FastAPI به یک Framework JavaScript فقط تبدیل Handler کافی نیست. باید این موارد مقایسه شوند:
- Path
- Method
- Query Parsing
- Validation
- Status Code
- Response Schema
- Serialization
- Middleware
- Dependency Injection
- Exception Mapping
- Streaming
- Lifecycle Hook
- OpenAPI
بهترین منبع مقایسه، OpenAPI و Contract Test است.
تبدیل تستها
مدل باید مفهوم تست را تبدیل کند، نه فقط Syntax آن را.
Pytest:
with pytest.raises(
ValueError,
match="invalid rate",
):
calculate(...)
Node Test:
assert.throws(
() => calculate(...),
/invalid rate/,
);
موارد مهم:
- Setup و Teardown
- Fixture
- Parametrize
- Async Test
- Mock
- Snapshot
- Error Matching
- Precision عددی
- Test Isolation
تبدیل پروژه چندفایلی
برای Repository بزرگ:
مرحله اول: Dependency Graph
مشخص کنید هر ماژول به چه اجزایی وابسته است.
مرحله دوم: Leaf Moduleها
ابتدا ماژولهایی را تبدیل کنید که Dependency داخلی کمتری دارند.
مرحله سوم: Contract Boundary
در مرز دو Runtime از JSON، HTTP، Queue یا Interface مشخص استفاده کنید.
مرحله چهارم: اجرای موازی
نسخه قدیمی و جدید برای بخشی از ورودیها همزمان اجرا و نتیجه مقایسه شوند.
مرحله پنجم: انتقال تدریجی
مصرفکنندهها مرحلهای به نسخه جدید منتقل شوند.
معماری Strangler برای مهاجرت تدریجی
Request
↓
Compatibility Layer
├── Old Python Module
└── New JavaScript Module
در مرحله مقایسه:
- نسخه قدیمی پاسخ اصلی را میدهد.
- نسخه جدید در پسزمینه همان ورودی را پردازش میکند.
- خروجیها مقایسه میشوند.
- اختلافها ثبت میشوند.
- پس از رسیدن به همارزی، مسیر اصلی تغییر میکند.
تولید مستقیم کل Repository چرا مناسب نیست؟
- Context بیش از حد بزرگ میشود.
- Dependencyها فراموش میشوند.
- رفتارهای ضمنی تغییر میکنند.
- Review Diff دشوار میشود.
- پیدا کردن علت اختلاف سخت میشود.
- تست هدفمند وجود ندارد.
- امکان Rollback کمتر میشود.
مهاجرت باید SymbolبهSymbol یا ModuleبهModule انجام شود.
تشخیص Hallucination در Code Translation
مدل ممکن است:
- کتابخانه موجودنبوده Import کند.
- Method خیالی بسازد.
- Type جدید اضافه کند.
- Validation را حذف کند.
- Exception را تغییر دهد.
- ورودی جدید فرض کند.
- Test Fixture را برای Pass شدن تغییر دهد.
- بخشی از Contract را نادیده بگیرد.
کنترلها:
- Allowlist مسیر فایل
- Allowlist Dependency
- Syntax Check
- Type Check
- Test مقصد
- Fixture مشترک
- Differential Test
- بررسی API عمومی
- مقایسه خروجی
- Review انسانی
ساخت Translation Report
گزارش نهایی باید شامل این موارد باشد:
{
"source": "Python 3.12",
"target": "Node.js 20 ESM",
"translated_modules": [
"pricing"
],
"tests": {
"source_passed": true,
"target_passed": true,
"differential_cases": 100,
"differences": 0
},
"known_differences": [
"JavaScript implementation rejects values outside safe integer range"
],
"unresolved_questions": [],
"ready_for_review": true
}
عبارت ready_for_review با ready_for_production یکسان نیست.
ارزیابی AI Code Translator
Dataset ارزیابی باید شامل این موارد باشد:
- تابع خالص
- Integer Division
- Float
- Decimal
- Unicode
- Date
- Regex
- Exception
- Dictionary و Object
- Set و Map
- Generator
- Async
- فایل و I/O
- Serialization
- API Endpoint
- ماژول چندفایلی
معیارها:
| معیار | توضیح |
|---|---|
| Parse Rate | کد مقصد از نظر Syntax معتبر است |
| Compile Rate | در زبانهای کامپایلشونده Build موفق است |
| Unit Test Pass Rate | تست مقصد موفق است |
| Differential Match | خروجی دو Runtime برابر است |
| Error Contract Match | رفتار خطا معادل است |
| Dependency Accuracy | کتابخانه خیالی اضافه نشده است |
| API Preservation | Contract عمومی حفظ شده است |
| Unsupported Behavior Detection | تفاوتهای غیرقابل تبدیل گزارش شدهاند |
| Human Edit Rate | میزان اصلاح دستی |
| Cost per Module | هزینه تبدیل هر ماژول |
انتخاب مدل مناسب
مدل مناسب باید در این زمینهها قوی باشد:
- درک زبان مبدأ
- تولید کد زبان مقصد
- تحلیل تفاوت معنایی
- پیروی از Specification
- خواندن تست
- تولید Structured Output
- مدیریت Context چندفایلی
- تولید Patch یا فایل محدود
برای تابعهای ساده، مدل سریعتر کافی است. برای مهاجرت Framework، Async Code یا ماژولهای چندفایلی، مدل قویتر مناسبتر خواهد بود.
فهرست مدلها و قیمتهای بهروز در صفحه مدلهای درواره قرار دارد.
مدیریت هزینه تبدیل کد
Plan را یکبار تولید کنید
برنامه مهاجرت را Cache و برای هر ماژول استفاده کنید.
فقط Context مرتبط
Source، Test، Specification و Dependencyهای همان ماژول ارسال شوند.
مرحلهای کار کنید
هر درخواست یک ماژول یا Symbol محدود را تبدیل کند.
ابزارهای قطعی را محلی اجرا کنید
Syntax، Test، Formatting و Type Check را مدل انجام ندهد.
کد بدون تغییر را دوباره ارسال نکنید
کلید Cache:
source_hash +
spec_hash +
test_hash +
target_runtime +
model_id +
prompt_version
اشتباهات رایج
ترجمه فقط بر اساس Syntax
رفتار عدد، تاریخ، Null و Exception باید بررسی شود.
نداشتن Specification
مدل رفتار فعلی را رفتار صحیح فرض میکند.
تغییر Fixture برای Pass شدن
Fixture مرجع نباید توسط Code Translator تغییر کند.
استفاده مستقیم از Float برای پول
دقت عددی مقصد باید صریحاً طراحی شود.
تبدیل کل Repository در یک درخواست
مهاجرت را ماژولبهماژول انجام دهید.
اعتماد به موفقیت Build
Build موفق به معنی یکسانبودن رفتار نیست.
مقایسه فقط Happy Path
Edge Case و Error Case نیز باید مقایسه شوند.
نادیدهگرفتن محدودیت Integer در JavaScript
مقادیر باید با Number.isSafeInteger بررسی یا با روش دیگری نمایش داده شوند.
انتشار بدون Differential Testing
هر دو Runtime باید روی ورودی یکسان اجرا شوند.
نقشه راه Production
مرحله اول: انتخاب ماژول خالص
یک تابع بدون I/O و Dependency پیچیده انتخاب کنید.
مرحله دوم: Contract و Fixture
رفتارها و نمونههای مرجع را ثبت کنید.
مرحله سوم: Migration Plan
تفاوتهای زبانها شناسایی شوند.
مرحله چهارم: تولید کد مقصد
فقط فایلهای مجاز ساخته شوند.
مرحله پنجم: Test مقصد
Syntax، Type و Unit Test اجرا شوند.
مرحله ششم: Differential Testing
ورودیهای ثابت و تولیدی روی هر دو نسخه اجرا شوند.
مرحله هفتم: اجرای موازی
در صورت امکان، خروجی نسخه جدید با نسخه قدیمی مقایسه شود.
مرحله هشتم: انتقال تدریجی
مصرفکنندهها مرحلهای منتقل شوند.
چکلیست تبدیل کد با AI
- زبان و نسخه مبدأ مشخص است.
- زبان و Runtime مقصد مشخص است.
- API عمومی ثبت شده است.
- Specification مستقل وجود دارد.
- تستهای مبدأ موفقاند.
- Fixture مشترک ساخته شده است.
- تفاوتهای معنایی بررسی شدهاند.
- Strategy دقت عددی مشخص است.
- رفتار Null و Undefined تعریف شده است.
- Exceptionها نگاشت شدهاند.
- Date و Timezone بررسی شدهاند.
- Regex در Runtime مقصد تست شده است.
- Dependency جدید کنترل شده است.
- فقط فایلهای مجاز تولید شدهاند.
- Syntax و Build مقصد موفقاند.
- Test مقصد موفق است.
- Differential Test اختلاف ندارد یا اختلاف تأیید شده است.
- API Key فقط در Backend نگهداری میشود.
- نتیجه توسط توسعهدهنده بررسی شده است.
پرسشهای متداول
آیا هوش مصنوعی میتواند کد را از یک زبان به زبان دیگر تبدیل کند؟
بله. AI میتواند Syntax، ساختار و بخش زیادی از منطق را تبدیل کند، اما همارزی رفتار باید با Specification، Test و Differential Testing تأیید شود.
چگونه Python را به JavaScript تبدیل کنیم؟
ابتدا API عمومی و رفتار Python را ثبت کنید، Fixture مشترک بسازید، تفاوتهای عدد، Null، Date و Exception را مشخص و سپس کد JavaScript را مرحلهای تولید و تست کنید.
آیا کد تبدیلشده مستقیماً قابل استفاده است؟
خیر. ابتدا باید Syntax، Dependency، Unit Test، Error Case و خروجی آن با نسخه مبدأ بررسی شود.
چرا خروجی Python و JavaScript متفاوت میشود؟
تفاوت در Float، Integer، Rounding، Truthiness، Unicode، Null، Date، Regex و Exception میتواند رفتار را تغییر دهد.
Differential Testing چیست؟
هر دو نسخه برنامه روی ورودی یکسان اجرا و خروجی یا خطای آنها مقایسه میشود.
برای مبلغ در JavaScript از چه روشی استفاده کنیم؟
برای بسیاری از کاربردها، نگهداری مبلغ در کوچکترین واحد پول بهصورت Integer مناسب است. برای عددهای بزرگ باید محدودیت Safe Integer یا استفاده از BigInt و Decimal Library بررسی شود.
آیا تبدیل کد همان Refactor است؟
خیر. Refactor معمولاً زبان و رفتار را حفظ میکند. تبدیل میان زبانها نوعی Migration یا Rewrite کنترلشده است.
آیا AI میتواند یک پروژه کامل را تبدیل کند؟
از نظر فنی میتواند بخشهای زیادی را تولید کند، اما تبدیل کامل باید مرحلهای، ماژولمحور و همراه تست و اجرای موازی باشد.
بهترین مدل برای ترجمه کد چیست؟
انتخاب مدل به زبانهای مبدأ و مقصد، حجم Context و پیچیدگی پروژه بستگی دارد. مدلها و قیمتهای بهروز را در صفحه مدلهای درواره مقایسه کنید.
API درواره چگونه استفاده میشود؟
در Backend یا ابزار محلی، base_url را روی https://api.darvareh.ir/v1 قرار دهید و Source، Specification، تست و Migration Plan را برای مدل ارسال کنید.
جمعبندی
تبدیل کد با هوش مصنوعی فقط جایگزینکردن Syntax یک زبان با زبان دیگر نیست. هدف واقعی، حفظ رفتار نرمافزار در Runtime مقصد است.
برای یک مهاجرت قابل اعتماد باید ابتدا Contract، Specification، Test Baseline و Fixture مشترک ساخته شوند. سپس تفاوتهای معنایی زبانها شناسایی و کد مقصد بهصورت مرحلهای تولید شود. در پایان، نسخه مبدأ و مقصد باید روی ورودی یکسان اجرا و مقایسه شوند.
در پروژه این مقاله یک AI Code Translator با Python، Node.js، Pydantic و API درواره ساختیم. نسخه Python موتور قیمتگذاری را به JavaScript ESM تبدیل کردیم، تستهای مشترک ساختیم و با Differential Testing همارزی خروجی دو Runtime را بررسی کردیم.
برای شروع، در درواره ثبتنام و API Key دریافت کنید. سپس مدل مناسب را از صفحه مدلهای درواره انتخاب کنید و مهاجرت را با یک تابع خالص، کوچک و دارای Test Suite آغاز کنید.
مقالات مرتبط
- ساخت دستیار برنامهنویسی اختصاصی برای شرکت
- بهترین مدل هوش مصنوعی برای برنامهنویسی
- بهترین ابزارهای برنامهنویسی با هوش مصنوعی؛ بخش اول
- بهترین ابزارهای برنامهنویسی با هوش مصنوعی؛ بخش دوم
- راهنمای Vibe Coding با هوش مصنوعی
- راهنمای AGENTS.md برای عاملهای برنامهنویسی
- آموزش Structured Outputs و JSON Schema
- آموزش ارزیابی مدلهای هوش مصنوعی و Evals
برای مطالعه شرایط استفاده و محدودیتهای مسئولیت، صفحه «سلب مسئولیت» را مشاهده کنید.