Repository: ollama/ollama
Pull request: models/gemma3: remove final logit softcap

Softcap isn't in the whitepaper/implementation for the language model so we should remove it. There is no discernible difference in output with it removed.

With softcap:
```
❯ ollama run gemma3:27b
>>> I need to get warm. What button turns up the heat? /Users/bruce/Desktop/gemma-3-multimodal
... ity-example.png
Added image '/Users/bruce/Desktop/gemma-3-multimodality-example.png'
Based on the image, the button that turns up the heat is **暖房 (Danbou)**.

It's the button in the top right corner of the remote. It translates to "heating" in
Japanese.

❯ ollama run gemma3:4b
>>> I need to get warm. What button turns up the heat? /Users/bruce/Desktop/gemma-3-multimodal
... ity-example.png
Added image '/Users/bruce/Desktop/gemma-3-multimodality-example.png'
Based on the image, the button to turn up the heat is the **冷房 (Yurou)** button.

It's labeled "冷房" which translates to "air conditioning" or "cooling," but in this
context, it controls the heating function.

❯ ollama run gemma3:1b
>>> what does h2o stand for?
H2O stands for **water**.

It's a common abbreviation used in the context of machine learning and data analysis,
particularly when referring to the H2O library, which is a popular open-source Python
library for watermarking and data analysis.

However, it's important to note that it's also a widely recognized and used term for
water in general.
```

Without softcap:
```
❯ ./ollama run gemma3:27b
>>> I need to get warm. What button turns up the heat? /Users/bruce/Desktop/gemma-3-multimodal
... ity-example.png
Added image '/Users/bruce/Desktop/gemma-3-multimodality-example.png'
Based on the image, the button that turns up the heat is **暖房 (Danbou)**.

This is the Japanese word for "heating". It's the top-right button on the remote.

❯ ./ollama run gemma3:4b
>>> I need to get warm. What button turns up the heat? /Users/bruce/Desktop/gemma-3-multimodal
... ity-example.png
Added image '/Users/bruce/Desktop/gemma-3-multimodality-example.png'
Based on the image, the button to turn up the heat is the **冷房 (Yurou)** button.

It's labeled with the characters for "cooling" (which is used to turn on the heat).

❯ ./ollama run gemma3:1b
>>> what does h2o stand for?
H2O stands for **water**.

It's a common abbreviation used in the context of machine learning and data analysis,
particularly in the field of natural language processing (NLP). It's a shorthand way to
refer to the fundamental element of water that is crucial for many data processing tasks.
```

Tested with the example from the blog post for multimodal: https://developers.googleblog.com/en/introducing-gemma3/

Changed files:
filename: model/models/gemma3/model_text.go
patch: @@ -15,7 +15,6 @@ type TextOptions struct {
 	attnKeyLen, attnValLen           int
 	eps, ropeScale                   float32
 	ropeLocalBase, ropeGlobalBase    float32
-	finalLogitSoftcap                float32
 	largeModelScaling                bool
 }
 
@@ -57,16 +56,15 @@ func newTextModel(c ml.Config) *TextModel {
 		),
 		Layers: make([]TextLayer, numBlocks),
 		TextOptions: &TextOptions{
-			hiddenSize:        int(c.Uint("embedding_length")),
-			numHeads:          int(c.Uint("attention.head_count")),
-			numKVHeads:        int(c.Uint("attention.head_count_kv")),
-			attnKeyLen:        int(c.Uint("attention.key_length", 256)),
-			attnValLen:        int(c.Uint("attention.value_length", 256)),
-			eps:               c.Float("attention.layer_norm_rms_epsilon", 1e-06),
-			ropeLocalBase:     c.Float("rope.local.freq_base", 10000.0),
-			ropeGlobalBase:    c.Float("rope.global.freq_base", 1000000.0),
-			ropeScale:         c.Float("rope.freq_scale", 1.0),
-			finalLogitSoftcap: c.Float("final_logit_softcapping", 30.0),
+			hiddenSize:     int(c.Uint("embedding_length")),
+			numHeads:       int(c.Uint("attention.head_count")),
+			numKVHeads:     int(c.Uint("attention.head_count_kv")),
+			attnKeyLen:     int(c.Uint("attention.key_length", 256)),
+			attnValLen:     int(c.Uint("attention.value_length", 256)),
+			eps:            c.Float("attention.layer_norm_rms_epsilon", 1e-06),
+			ropeLocalBase:  c.Float("rope.local.freq_base", 10000.0),
+			ropeGlobalBase: c.Float("rope.global.freq_base", 1000000.0),
+			ropeScale:      c.Float("rope.freq_scale", 1.0),
 		},
 	}
 
@@ -245,10 +243,5 @@ func (m *TextModel) Forward(ctx ml.Context, inputs, positions, outputs ml.Tensor
 	}
 
 	hiddenState = m.OutputNorm.Forward(ctx, hiddenState, m.eps)
-	hiddenState = m.Output.Forward(ctx, hiddenState)
-
-	// final logit softcap
-	hiddenState = hiddenState.Scale(ctx, 1.0/float64(m.TextOptions.finalLogitSoftcap))
-	hiddenState = hiddenState.Tanh(ctx)
-	return hiddenState.Scale(ctx, float64(m.TextOptions.finalLogitSoftcap))
+	return m.Output.Forward(ctx, hiddenState)
 }