This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Sunday, 09 November 2025
إذا كنت تتبع هذه المدونة، فأنت تعلم أنني مهووس قليلاً بالترجمة الآلية.لقد كتبت عن, Name Name Name Nameخدمات الترجمة التحريرية الأساسيةوحتى□ □ □ □ □ □ □ □ ٪**لكنني أدركت أنني لم أفسر في الواقع
كيف
أعمال الترجمة الآلية تحت غطاء المحرك.
ملاحظة: هذا جزء من تجاربي مع منظمة العفو الدولية/طريقة لإنفاق 1000 دولار من ائتمانات "كلوود" على شبكة الإنترنت.
ما هي الشبكات العصبية الاصطناعية وكيف تتعلّم
ما معنى "احذر" في AB (النفط: لا يتعلق الأمر بإيلاء الاهتمام)
graph LR
A[Source Sentence] --> B[Convert to Numbers]
B --> C[Neural Network Processing]
C --> D[Convert to Words]
D --> E[Translated Sentence]
الطريقة التي يعمل بها بنية العمية
لا تقلق إن لم تكن رياضياً سأبقي هذا عملياً وبصرياً قدر الإمكان
الفكرة الأساسية: الترجمة كإصدار عدد
دعونا نبدأ ببنات البناء.
graph LR
I1[Input 1] -->|weight: 0.8| N[Neuron]
I2[Input 2] -->|weight: -0.3| N
I3[Input 3] -->|weight: 0.5| N
N --> O[Output]
style N stroke-width:4px
الشبكات الخلقية الاصطناعية: المؤسسة
public class Neuron
{
private double[] weights;
private double bias;
public double Activate(double[] inputs)
{
// Step 1: Multiply each input by its weight and sum them
double sum = bias;
for (int i = 0; i < inputs.Length; i++)
{
sum += inputs[i] * weights[i];
}
// Step 2: Apply activation function (tanh keeps values between -1 and 1)
return Math.Tanh(sum);
}
}
قبل أن نتمكن من فهم الترجمة الآلية العصبية، نحن بحاجة إلى فهم الشبكات العصبية الاصطناعية.Math.Tanhعلى الرغم من الاسم الفاخر، فهي في الواقع بسيطة جدا في جوهرها.
الاعصاب الاصطناعي عبارة عن اقتران رياضي
graph LR
subgraph Input Layer
I1[Input 1]
I2[Input 2]
I3[Input 3]
end
subgraph Hidden Layer 1
H1[Neuron 1]
H2[Neuron 2]
H3[Neuron 3]
H4[Neuron 4]
end
subgraph Hidden Layer 2
H5[Neuron 5]
H6[Neuron 6]
H7[Neuron 7]
end
subgraph Output Layer
O1[Output 1]
O2[Output 2]
end
I1 --> H1 & H2 & H3 & H4
I2 --> H1 & H2 & H3 & H4
I3 --> H1 & H2 & H3 & H4
H1 --> H5 & H6 & H7
H2 --> H5 & H6 & H7
H3 --> H5 & H6 & H7
H4 --> H5 & H6 & H7
H5 --> O1 & O2
H6 --> O1 & O2
H7 --> O1 & O2
يَدِِِِِِدِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِِ
لنجعل هذا مثبتاً ببعض الرموز C#:
graph TD
A[Start with Random Weights] --> B[Feed in Training Example]
B --> C[Network Makes Prediction]
C --> D{Is Prediction Correct?}
D -->|No| E[Calculate Error]
E --> F[Adjust Weights Slightly]
F --> B
D -->|Yes| G[Try Next Example]
G --> B
style E stroke-width:2px
style F stroke-width:2px
الدالة الدالة التحفيز (في هذه الحالة)**هو ما يجعل الشبكات العصبية مثيرة للاهتمام.**فهو يُدخل غير الخطي، مما يسمح للشبكة بتعلم أنماط معقدة.
بدونه، بغض النظر عن عدد الخلايا العصبية التي جمعتها معاً، سيكون لديك فقط اقتران خطي مبهرج.
public class SimpleNeuralNetwork
{
private double learningRate = 0.01;
private Neuron[] neurons;
public void Train(TrainingExample[] examples, int epochs)
{
for (int epoch = 0; epoch < epochs; epoch++)
{
foreach (var example in examples)
{
// Forward pass: make a prediction
double prediction = Predict(example.Input);
// Calculate error
double error = example.ExpectedOutput - prediction;
// Backward pass: adjust weights
// (simplified - real networks use backpropagation)
AdjustWeights(error * learningRate);
}
}
}
}
من العنان إلى الشبكات**يحدث السحر عندما تربط الآلاف أو الملايين من هذه الخلايا العصبية معاً في طبقات:**كل طبقة "تكيف" تمثيل المدخلات، وتستخرج الأنماط التجريدية بشكل متزايد.
الطبقات المبكّرة قد تكتشف "هذا هو فعل" أو "هذه الكلمة هي ماضٍ من التوتر"
الطبقات المتأخرة تجمع هذه إلى "ترجمة هذا كسؤال مهذب حول طقس الغد"
// Don't do this!
var wordToNumber = new Dictionary<string, int>
{
{"cat", 1},
{"dog", 2},
{"king", 3},
{"queen", 4},
{"man", 5},
{"woman", 6}
};
كيفية تعلم الشبكات: عملية التدريب
وتتعلمهم الشبكة من الامثلة !هذه العملية دُعيتالميـج
public class WordEmbedding
{
// Each word is represented by a vector of floats
private Dictionary<string, float[]> embeddings;
public float[] GetEmbedding(string word)
{
return embeddings[word]; // e.g., [0.2, -0.5, 0.8, 0.1, ...]
}
// Calculate similarity between two words
public double Similarity(string word1, string word2)
{
var vec1 = GetEmbedding(word1);
var vec2 = GetEmbedding(word2);
// Cosine similarity: how "aligned" are the vectors?
return CosineSimilarity(vec1, vec2);
}
private double CosineSimilarity(float[] a, float[] b)
{
double dot = 0, magA = 0, magB = 0;
for (int i = 0; i < a.Length; i++)
{
dot += a[i] * b[i];
magA += a[i] * a[i];
magB += b[i] * b[i];
}
return dot / (Math.Sqrt(magA) * Math.Sqrt(magB));
}
}
graph TD
subgraph "2D Projection of 300D Space"
King[King<br/>0.8, 0.6]
Queen[Queen<br/>0.75, 0.55]
Man[Man<br/>0.3, 0.2]
Woman[Woman<br/>0.25, 0.15]
Dog[Dog<br/>-0.6, 0.4]
Cat[Cat<br/>-0.65, 0.38]
end
King -.similar.-> Queen
Man -.similar.-> Woman
Dog -.similar.-> Cat
King -.same vector.-> Man
Queen -.same vector.-> Woman
بالنسبة لكل إجابة خاطئة، تستنتج الشبكة "أي الأوزان هي الأكثر مسؤولية عن هذا الخطأ؟" وتحوّلها قليلاً.king - man + woman ≈ queen
public float[] AnalogicalReasoning(string a, string b, string c)
{
// king - man + woman = ?
var vecA = GetEmbedding(a); // king
var vecB = GetEmbedding(b); // man
var vecC = GetEmbedding(c); // woman
var result = new float[vecA.Length];
for (int i = 0; i < vecA.Length; i++)
{
result[i] = vecA[i] - vecB[i] + vecC[i];
}
// Find the word closest to this vector
return FindClosestWord(result); // Should return "queen"
}
هذه نسخة مبسطة في C#:
graph LR
A["The cat sat on the mat"] --> B[Train Neural Network]
B --> C["cat → [0.1, 0.5, -0.3, ...]"]
B --> D["sat → [0.2, -0.1, 0.4, ...]"]
B --> E["mat → [0.15, 0.45, -0.25, ...]"]
الشبكات الحقيقية التي تستخدم خوارزمية أكثر تطوراً تدعى
الذي يقوم بكفاءة بحساب كيفية تعديل الأوزان في كامل الشبكة، لكن المبدأ هو نفسه: تعلم من الأخطاء.
graph TD
subgraph English
E1[The]
E2[cat]
E3[sat]
E4[on]
E5[the]
E6[mat]
end
subgraph French
F1[Le]
F2[chat]
F3[s'est assis]
F4[sur]
F5[le]
F6[tapis]
end
E2 -. focus 90% .-> F2
E3 -. focus 70% .-> F3
E4 -. focus 80% .-> F4
E6 -. focus 85% .-> F6
E1 -. focus 30% .-> F1
ترجمة اللغة إلى رياضياتالآن وصلنا إلى التحدي الرئيسي الأول: كيف نغذي الكلمات في شبكة عصبية؟
المشكلة مع التر تش تشفر مع مُرْفِز مُرْفَز مُرْفَز مُرْفَز مُرْفَز مُرفَز مُرفَز مَ مَ مَ مَ مُرفَز مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ تشفر مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ تشفر مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ م تش تش تش تش تش تش تش تش تش تشز مَ مَ مَ مَ مَ مَ مَ مَ مَ مَ مُ مُ مُ مُ مُ م تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش م م م م م م م م م م م م م م م م مُ م- م- م- م- م- م- م- م- م م- م- م- م- م- م- م م- م- م تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش م م م م تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش م م م م م م م م م م م م م م م م م م تش تش م م م م م م م م م م م م م م م م م م م م م م م تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش تش م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م تش تش تش تش تش تش تش م م م م م م م م م م م م م م م م م م م
public class AttentionMechanism
{
// Calculate attention weights for each source word
public double[] CalculateAttention(
float[] currentTargetState, // Where we are in translation
float[][] sourceWordStates) // All source words
{
int sourceLength = sourceWordStates.Length;
double[] scores = new double[sourceLength];
// Step 1: Calculate relevance scores
for (int i = 0; i < sourceLength; i++)
{
scores[i] = DotProduct(currentTargetState, sourceWordStates[i]);
}
// Step 2: Convert to probabilities (softmax)
return Softmax(scores);
}
public float[] ApplyAttention(
double[] attentionWeights,
float[][] sourceWordStates)
{
// Create weighted average of source words
int dim = sourceWordStates[0].Length;
float[] result = new float[dim];
for (int i = 0; i < sourceWordStates.Length; i++)
{
for (int j = 0; j < dim; j++)
{
result[j] += (float)(attentionWeights[i] * sourceWordStates[i][j]);
}
}
return result;
}
private double[] Softmax(double[] scores)
{
double[] result = new double[scores.Length];
double sum = 0;
for (int i = 0; i < scores.Length; i++)
{
result[i] = Math.Exp(scores[i]);
sum += result[i];
}
for (int i = 0; i < scores.Length; i++)
{
result[i] /= sum;
}
return result;
}
private double DotProduct(float[] a, float[] b)
{
double sum = 0;
for (int i = 0; i < a.Length; i++)
{
sum += a[i] * b[i];
}
return sum;
}
}
النهج الساذج هو "واحد-حارس-الترميز" --تخصيص كل كلمة رقماً فريداً:
(ن)
graph TD
subgraph "English (Source)"
E1[The]
E2[agreement]
E3[on]
E4[the]
E5[European]
E6[Economic]
E7[Area]
end
subgraph "German (Target)"
G1[Das]
G2[Abkommen]
G3[über]
G4[den]
G5[Europäischen]
end
E1 -->|0.8| G1
E2 -->|0.9| G2
E3 -->|0.6| G3
E4 -->|0.3| G3
E5 -->|0.85| G5
E6 -->|0.7| G5
من الأعداد، عادة 300 إلى 1000 أبعاد.
هذا ما يجعل التزكية سحرية - أنها تلتقط العلاقات الدلالية:**المثال الشهير:**كيف تُعلَّم التعاليم ؟
graph LR
subgraph "Self-Attention for 'bank'"
B[bank]
R[river]
W[water]
F[fish]
end
B -.high attention.-> R
B -.high attention.-> W
B -.medium attention.-> F
تُتَعَلَّم الأسر من خلال تدريب شبكة عصبية على مهمة بسيطة: "توقع الكلمات المحيطة".
بعد التدريب على مليارات الجمل، الكلمات التي تظهر في سياقات متشابهة ينتهي بها المطاف بدمجات متشابهة. "Cat" و"Dog" كلاهما يظهران بالقرب من "pet" و"fed" و"come" و"compecte"، وبالتالي فإن دمجهما ينتهيان معاً.المصدر: الـ الـ مُغيّر الـ مُستخدِر الـ مُغيّرهذه هي البصيرة الحرجة: عند ترجمة "القط جلس على السجادة" إلى الفرنسية،
graph LR
subgraph Encoder
E1[Word Embeddings] --> E2[Self-Attention Layer 1]
E2 --> E3[Self-Attention Layer 2]
E3 --> E4[Self-Attention Layer N]
E4 --> E5[Contextual Representations]
end
subgraph Decoder
D1[Previous Translations] --> D2[Self-Attention]
D2 --> D3[Cross-Attention to Encoder]
D3 --> D4[Feed Forward]
D4 --> D5[Next Word Prediction]
end
E5 -.provides context.-> D3
هو آلية تسمح للشبكة "بالتركيز" على أجزاء مختلفة من المدخلات عند توليد كل كلمة مخرج.
public class TransformerEncoder
{
private WordEmbedding wordEmbedding;
private SelfAttentionLayer[] layers;
public float[][] Encode(string[] sourceWords)
{
// Step 1: Convert words to embeddings
float[][] embeddings = sourceWords
.Select(w => wordEmbedding.GetEmbedding(w))
.ToArray();
// Step 2: Add positional encoding (so network knows word order)
float[][] withPositions = AddPositionalEncoding(embeddings);
// Step 3: Apply multiple self-attention layers
float[][] representations = withPositions;
foreach (var layer in layers)
{
representations = layer.Forward(representations);
}
return representations; // Contextual representations for each word
}
private float[][] AddPositionalEncoding(float[][] embeddings)
{
// Add position-specific patterns so network knows word order
// (transformers don't naturally understand sequence order)
int sequenceLength = embeddings.Length;
int embeddingDim = embeddings[0].Length;
for (int pos = 0; pos < sequenceLength; pos++)
{
for (int i = 0; i < embeddingDim; i++)
{
double angle = pos / Math.Pow(10000, (2.0 * i) / embeddingDim);
// Use sine for even dimensions, cosine for odd
embeddings[pos][i] += (float)(i % 2 == 0 ? Math.Sin(angle) : Math.Cos(angle));
}
}
return embeddings;
}
}
كيف يعمل الاهتمام
حوّل درجات إلى احتمالات (تُجمع إلى 1)
public class TransformerDecoder
{
private WordEmbedding targetEmbedding;
private SelfAttentionLayer[] selfAttentionLayers;
private CrossAttentionLayer[] crossAttentionLayers;
private FeedForwardLayer[] feedForwardLayers;
public string[] Decode(float[][] encodedSource, int maxLength)
{
List<string> translation = new List<string>();
translation.Add("<START>"); // Special token to begin
while (translation.Count < maxLength)
{
// Get next word
string nextWord = GenerateNextWord(encodedSource, translation.ToArray());
if (nextWord == "<END>") break; // Stop token
translation.Add(nextWord);
}
return translation.Skip(1).ToArray(); // Remove <START> token
}
private string GenerateNextWord(float[][] encodedSource, string[] partialTranslation)
{
// Step 1: Embed the partial translation
float[][] targetEmbeddings = partialTranslation
.Select(w => targetEmbedding.GetEmbedding(w))
.ToArray();
// Step 2: Self-attention on target words
float[][] selfAttended = ApplySelfAttention(targetEmbeddings);
// Step 3: Cross-attention to source (this is where translation happens!)
float[][] crossAttended = ApplyCrossAttention(selfAttended, encodedSource);
// Step 4: Feed forward
float[] finalState = ApplyFeedForward(crossAttended[^1]); // Last position
// Step 5: Predict next word
return PredictWord(finalState);
}
private string PredictWord(float[] state)
{
// Convert state to probability distribution over all possible words
Dictionary<string, double> wordProbabilities = CalculateWordProbabilities(state);
// Return most likely word (or sample from distribution)
return wordProbabilities.OrderByDescending(kv => kv.Value).First().Key;
}
}
ينشئ متوسطاً مرجحاً لكلمات المصدر على أساس هذه الاحتمالات
sequenceDiagram
participant Input as Source Sentence
participant Encoder
participant Decoder
participant Output as Translation
Input->>Encoder: "The cat sat"
Encoder->>Encoder: Build representations
Encoder->>Decoder: Encoded states
Decoder->>Decoder: Generate [START]
Decoder->>Output: Emit START token
Decoder->>Decoder: Attend to "The" → Generate "Le"
Decoder->>Output: "Le"
Decoder->>Decoder: Attend to "cat" → Generate "chat"
Decoder->>Output: "chat"
Decoder->>Decoder: Attend to "sat" → Generate "s'est assis"
Decoder->>Output: "s'est assis"
Decoder->>Decoder: Generate [END]
Output->>Output: "Le chat s'est assis"
عند ترجمة "الاتفاق على المنطقة الاقتصادية الأوروبية تم التوقيع عليه في أغسطس 1992" إلى الألمانية، يبدو الاهتمام مثل هذا:
public class TranslationTrainer
{
private TransformerEncoder encoder;
private TransformerDecoder decoder;
private double learningRate = 0.0001;
public void Train(ParallelCorpus corpus, int epochs)
{
foreach (var epoch in Enumerable.Range(0, epochs))
{
double totalLoss = 0;
int batchCount = 0;
foreach (var batch in corpus.GetBatches(batchSize: 32))
{
// Forward pass
var predictions = new List<string[]>();
var losses = new List<double>();
foreach (var pair in batch)
{
// Encode source
var encoded = encoder.Encode(pair.Source);
// Try to decode target
var predicted = decoder.Decode(encoded, pair.Target.Length);
// Calculate loss (how different is prediction from target?)
double loss = CalculateLoss(predicted, pair.Target);
losses.Add(loss);
}
// Backward pass: adjust weights
double avgLoss = losses.Average();
UpdateWeights(avgLoss);
totalLoss += avgLoss;
batchCount++;
}
Console.WriteLine($"Epoch {epoch}: Average Loss = {totalLoss / batchCount}");
}
}
private double CalculateLoss(string[] predicted, string[] target)
{
// Cross-entropy loss: how far off were our word predictions?
double loss = 0;
for (int i = 0; i < Math.Min(predicted.Length, target.Length); i++)
{
if (predicted[i] != target[i])
{
loss += 1.0; // Simplified - real loss is more nuanced
}
}
return loss / target.Length;
}
private void UpdateWeights(double loss)
{
// Backpropagation: adjust all weights in encoder and decoder
// to reduce the loss (simplified here)
// Real implementation uses automatic differentiation
}
}
الـ مُفكّر مُفكّر مُعَدّ
graph TD
A[10M Sentence Pairs] --> B[Initial Random Weights]
B --> C[Epoch 1: Loss = 5.2]
C --> D[Epoch 2: Loss = 3.8]
D --> E[Epoch 3: Loss = 2.1]
E --> F[Epoch 10: Loss = 0.8]
F --> G[Epoch 20: Loss = 0.3]
G --> H[Trained Model!]
style A stroke-width:2px
style H stroke-width:4px
الآن يمكننا أن نضعها معاً!
موقعه في الجملة (من الترميز الموضعي)
graph TD
subgraph "1. Encoding"
A1[The] --> E1[emb: 0.2, -0.1, ...]
A2[cat] --> E2[emb: 0.5, 0.3, ...]
A3[sat] --> E3[emb: -0.1, 0.4, ...]
A4[on] --> E4[emb: 0.1, -0.2, ...]
A5[the] --> E5[emb: 0.2, -0.1, ...]
A6[mat] --> E6[emb: 0.4, 0.2, ...]
end
subgraph "2. Self-Attention in Encoder"
E1 & E2 & E3 & E4 & E5 & E6 --> SA[Self-Attention]
SA --> C1[ctx: 0.3, 0.1, ...]
SA --> C2[ctx: 0.6, 0.4, ...]
SA --> C3[ctx: -0.2, 0.5, ...]
end
subgraph "3. Decoding"
D1[START] --> G1[Le]
C2 -.attend.-> G1
G1 --> G2[chat]
C2 -.attend.-> G2
G2 --> G3[s'est assis]
C3 -.attend.-> G3
end
المفكفكفك مفك مفك مفك مفك مفك مفك مفك مفك مفك مفك مفك مفك مفك مفك مفك مفك مفك المفك: محرف الترجمة
var theEmbedding = encoder.GetEmbedding("The");
// [0.2, -0.1, 0.3, 0.05, ..., 0.1] (300 dimensions)
الدالة المفككة تولد الترجمة كلمة واحدة في كل مرة:
var catEmbedding = encoder.GetEmbedding("cat");
// [0.5, 0.3, -0.2, 0.4, ..., 0.15] (300 dimensions)
عملية الترجمة الكاملة:
// "cat" attends to other words
var catAttention = attention.CalculateAttention(catEmbedding, allWordEmbeddings);
// [0.1, 0.3, 0.2, 0.05, 0.1, 0.25]
// High attention to "sat" (0.3) and "mat" (0.25)
var catContextual = attention.ApplyAttention(catAttention, allWordEmbeddings);
// Weighted average incorporating context
نموذج التدريب على الترجمة
var decoderState = decoder.InitialState();
ويتطلب التدريب على نموذج الترجمة ثلاثة أمور:
// Attend to source
var sourceAttention = crossAttention.Calculate(decoderState, encodedSource);
// [0.8, 0.05, 0.05, 0.02, 0.05, 0.03]
// Strong focus on "The" (0.8)
var nextWordProbs = decoder.PredictNextWord(decoderState, sourceAttention);
// {"Le": 0.85, "La": 0.08, "Les": 0.04, ...}
var firstWord = "Le";
مفرصة
decoderState = decoder.UpdateState(decoderState, "Le");
var sourceAttention = crossAttention.Calculate(decoderState, encodedSource);
// [0.05, 0.9, 0.02, 0.01, 0.01, 0.01]
// Strong focus on "cat" (0.9)
var nextWordProbs = decoder.PredictNextWord(decoderState, sourceAttention);
// {"chat": 0.92, "chien": 0.03, ...}
var secondWord = "chat";
: بملايين الجمل في لغتي كل من اللغتين:
Final translation: "Le chat s'est assis sur le tapis"
كيف "خطأ" كان تنبؤنا؟
graph LR
subgraph "Old: Recurrent Neural Networks"
R1[Word 1] --> R2[Word 2]
R2 --> R3[Word 3]
R3 --> R4[Word 4]
end
subgraph "New: Transformers"
T1[Word 1] -.attend.-> T2[Word 2]
T1 -.attend.-> T3[Word 3]
T1 -.attend.-> T4[Word 4]
T2 -.attend.-> T3
T2 -.attend.-> T4
T3 -.attend.-> T4
end
النموذج
public class TranslationService
{
private readonly HttpClient _httpClient;
private readonly string _nmtServiceUrl;
public TranslationService(HttpClient httpClient, IConfiguration config)
{
_httpClient = httpClient;
_nmtServiceUrl = config["NMT:ServiceUrl"];
}
public async Task<TranslationResult> TranslateAsync(
string text,
string sourceLang,
string targetLang)
{
var request = new TranslationRequest
{
Text = new[] { text },
SourceLang = sourceLang,
TargetLang = targetLang
};
var response = await _httpClient.PostAsJsonAsync(
$"{_nmtServiceUrl}/translate",
request);
response.EnsureSuccessStatusCode();
var result = await response.Content
.ReadFromJsonAsync<TranslationResponse>();
return new TranslationResult
{
Original = text,
Translated = result.Translated[0],
SourceLanguage = sourceLang,
TargetLanguage = targetLang,
TranslationTime = result.TranslationTime
};
}
}
public class TranslationRequest
{
[JsonPropertyName("text")]
public string[] Text { get; set; }
[JsonPropertyName("source_lang")]
public string SourceLang { get; set; }
[JsonPropertyName("target_lang")]
public string TargetLang { get; set; }
}
public class TranslationResponse
{
[JsonPropertyName("translated")]
public string[] Translated { get; set; }
[JsonPropertyName("translation_time")]
public double TranslationTime { get; set; }
}
100M إلى 1B+ البارامترات (الوزنات): 100M إلى 1B+
// In your controller or service
public class BlogPostController : ControllerBase
{
private readonly TranslationService _translator;
public async Task<IActionResult> TranslatePost(int postId, string targetLang)
{
var post = await _blogService.GetPostAsync(postId);
var translatedTitle = await _translator.TranslateAsync(
post.Title,
"en",
targetLang);
var translatedContent = await _translator.TranslateAsync(
post.Content,
"en",
targetLang);
return Ok(new
{
Title = translatedTitle.Translated,
Content = translatedContent.Translated,
OriginalLanguage = "en",
TargetLanguage = targetLang
});
}
}
عملية الخطوة خطوة خطوة:
public async Task<string> TranslateLongText(string longText, string targetLang)
{
const int maxChunkSize = 500; // characters
// Split on paragraph boundaries
var paragraphs = longText.Split(new[] { "\n\n", "\r\n\r\n" },
StringSplitOptions.RemoveEmptyEntries);
var translatedParagraphs = new List<string>();
foreach (var paragraph in paragraphs)
{
if (paragraph.Length <= maxChunkSize)
{
var result = await _translator.TranslateAsync(paragraph, "en", targetLang);
translatedParagraphs.Add(result.Translated);
}
else
{
// Split long paragraph into sentences
var sentences = SplitIntoSentences(paragraph);
var translatedSentences = new List<string>();
foreach (var sentence in sentences)
{
var result = await _translator.TranslateAsync(sentence, "en", targetLang);
translatedSentences.Add(result.Translated);
}
translatedParagraphs.Add(string.Join(" ", translatedSentences));
}
}
return string.Join("\n\n", translatedParagraphs);
}
الخطوة: خطوة: مُسند "كات"
public async Task<string> TranslateMarkdown(string markdown, string targetLang)
{
// Extract text from markdown while preserving structure
var doc = Markdig.Markdown.Parse(markdown);
var textSegments = new List<(string text, int position)>();
// Walk the AST and extract translatable text
foreach (var node in doc.Descendants())
{
if (node is LiteralInline literal)
{
var text = literal.Content.ToString();
if (!string.IsNullOrWhiteSpace(text) && !IsImagePath(text))
{
textSegments.Add((text, literal.Span.Start));
}
}
}
// Translate all segments
var translations = await Task.WhenAll(
textSegments.Select(async seg => new
{
seg.position,
translated = (await _translator.TranslateAsync(seg.text, "en", targetLang)).Translated
}));
// Reconstruct markdown with translations
var result = markdown;
foreach (var translation in translations.OrderByDescending(t => t.position))
{
result = result.Remove(translation.position, textSegments
.First(s => s.position == translation.position).text.Length)
.Insert(translation.position, translation.translated);
}
return result;
}
خطوة 4: تنفيذ مفكفكفكفك مع
public async Task<Dictionary<string, string>> TranslateBatch(
IEnumerable<string> texts,
string targetLang)
{
const int batchSize = 32;
var results = new Dictionary<string, string>();
foreach (var batch in texts.Chunk(batchSize))
{
var request = new TranslationRequest
{
Text = batch.ToArray(),
SourceLang = "en",
TargetLang = targetLang
};
var response = await _httpClient.PostAsJsonAsync(
$"{_nmtServiceUrl}/translate",
request);
var result = await response.Content
.ReadFromJsonAsync<TranslationResponse>();
for (int i = 0; i < batch.Length; i++)
{
results[batch[i]] = result.Translated[i];
}
}
return results;
}
الخطوة 6: خلق "محادثة"
graph TD
A[Translation Request] --> B{Model Size}
B -->|Small 100M params| C[Fast: 50-100ms]
B -->|Medium 500M params| D[Medium: 200-500ms]
B -->|Large 1B+ params| E[Slow: 1-3 seconds]
A --> F{Hardware}
F -->|CPU| G[Slow: 2-5x slower]
F -->|GPU| H[Fast: Baseline]
F -->|TPU/Special AI chips| I[Very Fast: 2-3x faster]
style C stroke-width:2px
style E stroke-width:2px
الخطوة 7: الاستمرار حتى
****:: مزيد من البيانات + نموذج أكبر = نتائج أفضل (حتى نقطة)
**وتسير الشبكات المتكررة بشكل متتابع (منخفضة) في حين تقوم المحولات بتجهيز جميع الكلمات في آن واحد (متسارعة!).**استخدام NMMT في C#: مثال عملي
ترجمة جملة واحدة في وقت واحد أمر بطيء.
! اقبضوا عليهم
(1B+ B+ parms): 1-3 ثوان
Now when you hit "translate" on your blog posts, you'll know exactly what's happening under the hood! 🚀
:GPU هو 2-10x أسرع من NMT
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.