Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit 09aefd5

Browse files
authored
config(cody): Various fixes and updating the naming rules for ModelConfig resource IDs (#63436)
The `internal/modelconfig` package provides the schema by which Sourcegraph instances will keep track of LLM providers, models, and various configuration settings. The `cmd/cody-gateway-config` tool writes a JSON file contains the model configuration data for Cody Gateway. This PR fixes an assortment if problems with these components. d8963da - Due to a logic error, we were saving the model ID of "unknown" into `models.json`. We now put the actual `ModelID` from the `ModelRef`. d9baa65 - Updates the model information that gets rendered, so that it matches what is hard-coded into the `sourcegraph/cody` repo. (We were missing any reference to the newly added Google Gemini models.) c28780c - Relaxes the resource ID regular expression so that it is now legal to add periods. So "gemini-1.5-latest" is now considered a valid `ModelID`. ... however, the validation checks were incorrectly passing because there was a bug in the regular expression. And after writing some unit tests for the `validateModelRef` function, I found several other problems with that regular expression 😅 . But we should be much closer to things working as intended now. ## Test plan Added tests
1 parent c3ce26f commit 09aefd5

File tree

5 files changed

+160
-33
lines changed

5 files changed

+160
-33
lines changed

cmd/cody-gateway-config/dotcom_models.go

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func getAnthropicModels() []types.Model {
6464
// Pro Anthropic models.
6565
newModel(
6666
modelIdentity{
67-
MRef: mRef(anthropic_06_2023, "claude-3-5-sonnet"),
67+
MRef: mRef(anthropic_06_2023, "claude-3.5-sonnet"),
6868
Name: "claude-3-5-sonnet-20240620",
6969
DisplayName: "Claude 3.5 Sonnet",
7070
},
@@ -145,6 +145,43 @@ func getAnthropicModels() []types.Model {
145145
}
146146
}
147147

148+
func getGoogleModels() []types.Model {
149+
const (
150+
// Gemini API versions.
151+
// https://ai.google.dev/gemini-api/docs/api-versions
152+
geminiV1 = "google::v1"
153+
)
154+
155+
return []types.Model{
156+
newModel(
157+
modelIdentity{
158+
MRef: mRef(geminiV1, "gemini-1.5-pro-latest"),
159+
Name: "gemini-1.5-pro-latest",
160+
DisplayName: "Gemini 1.5 Pro",
161+
},
162+
modelMetadata{
163+
Capabilities: chatAndEdit,
164+
Category: types.ModelCategoryAccuracy,
165+
Status: types.ModelStatusStable,
166+
Tier: types.ModelTierPro,
167+
},
168+
expandedCtxWindow),
169+
newModel(
170+
modelIdentity{
171+
MRef: mRef(geminiV1, "gemini-1.5-flash-latest"),
172+
Name: "google/gemini-1.5-flash-latest",
173+
DisplayName: "Gemini 1.5 Flash",
174+
},
175+
modelMetadata{
176+
Capabilities: chatAndEdit,
177+
Category: types.ModelCategorySpeed,
178+
Status: types.ModelStatusStable,
179+
Tier: types.ModelTierPro,
180+
},
181+
expandedCtxWindow),
182+
}
183+
}
184+
148185
func getMistralModels() []types.Model {
149186
// Not sure if there is a canonical API reference, since Mixtral offers 3rd
150187
// party LLMs as a service.
@@ -209,7 +246,7 @@ func getOpenAIModels() []types.Model {
209246
},
210247
modelMetadata{
211248
Capabilities: chatAndEdit,
212-
Category: types.ModelCategoryAccuracy,
249+
Category: types.ModelCategoryBalanced,
213250
Status: types.ModelStatusStable,
214251
Tier: types.ModelTierPro,
215252
},
@@ -238,6 +275,7 @@ func GetCodyFreeProModels() ([]types.Model, error) {
238275
// ================================================
239276
var allModels []types.Model
240277
allModels = append(allModels, getAnthropicModels()...)
278+
allModels = append(allModels, getGoogleModels()...)
241279
allModels = append(allModels, getMistralModels()...)
242280
allModels = append(allModels, getOpenAIModels()...)
243281

cmd/cody-gateway-config/utils.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func newModel(identity modelIdentity, metadata modelMetadata, ctxWindow types.Co
3838
// before writing it out.
3939
modelID := types.ModelID("unknown")
4040
parts := strings.Split(string(identity.MRef), "::")
41-
if len(parts) != 3 {
41+
if len(parts) == 3 {
4242
modelID = types.ModelID(parts[2])
4343
}
4444

internal/modelconfig/embedded/models.json

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
],
2222
"models": [
2323
{
24-
"modelId": "unknown",
24+
"modelId": "claude-3-sonnet",
2525
"modelRef": "anthropic::2023-06-01::claude-3-sonnet",
2626
"displayName": "Claude 3 Sonnet",
2727
"string": "claude-3-sonnet-20240229",
28-
"capabilities": ["chat", "edit"],
28+
"capabilities": ["autocomplete", "chat"],
2929
"category": "balanced",
3030
"status": "stable",
3131
"tier": "free",
@@ -35,11 +35,11 @@
3535
}
3636
},
3737
{
38-
"modelId": "unknown",
39-
"modelRef": "anthropic::2023-06-01::claude-3-5-sonnet",
38+
"modelId": "claude-3.5-sonnet",
39+
"modelRef": "anthropic::2023-06-01::claude-3.5-sonnet",
4040
"displayName": "Claude 3.5 Sonnet",
4141
"string": "claude-3-5-sonnet-20240620",
42-
"capabilities": ["chat", "edit"],
42+
"capabilities": ["autocomplete", "chat"],
4343
"category": "accuracy",
4444
"status": "stable",
4545
"tier": "pro",
@@ -49,11 +49,11 @@
4949
}
5050
},
5151
{
52-
"modelId": "unknown",
52+
"modelId": "claude-3-opus",
5353
"modelRef": "anthropic::2023-06-01::claude-3-opus",
5454
"displayName": "Claude 3 Opus",
5555
"string": "claude-3-opus-20240229",
56-
"capabilities": ["chat", "edit"],
56+
"capabilities": ["autocomplete", "chat"],
5757
"category": "accuracy",
5858
"status": "stable",
5959
"tier": "pro",
@@ -63,11 +63,11 @@
6363
}
6464
},
6565
{
66-
"modelId": "unknown",
66+
"modelId": "claude-3-haiku",
6767
"modelRef": "anthropic::2023-06-01::claude-3-haiku",
6868
"displayName": "Claude 3 Haiku",
6969
"string": "claude-3-haiku-20240307",
70-
"capabilities": ["chat", "edit"],
70+
"capabilities": ["autocomplete", "chat"],
7171
"category": "speed",
7272
"status": "stable",
7373
"tier": "pro",
@@ -77,11 +77,11 @@
7777
}
7878
},
7979
{
80-
"modelId": "unknown",
80+
"modelId": "claude-2.1",
8181
"modelRef": "anthropic::2023-01-01::claude-2.1",
8282
"displayName": "Claude 2.1",
8383
"string": "claude-2.1",
84-
"capabilities": ["chat", "edit"],
84+
"capabilities": ["autocomplete", "chat"],
8585
"category": "balanced",
8686
"status": "deprecated",
8787
"tier": "free",
@@ -91,11 +91,11 @@
9191
}
9292
},
9393
{
94-
"modelId": "unknown",
94+
"modelId": "claude-2.0",
9595
"modelRef": "anthropic::2023-01-01::claude-2.0",
9696
"displayName": "Claude 2.0",
9797
"string": "claude-2.0",
98-
"capabilities": ["chat", "edit"],
98+
"capabilities": ["autocomplete", "chat"],
9999
"category": "balanced",
100100
"status": "deprecated",
101101
"tier": "free",
@@ -105,11 +105,11 @@
105105
}
106106
},
107107
{
108-
"modelId": "unknown",
108+
"modelId": "claude-instant-1.2",
109109
"modelRef": "anthropic::2023-01-01::claude-instant-1.2",
110110
"displayName": "Claude Instant",
111111
"string": "claude-instant-1.2",
112-
"capabilities": ["chat", "edit"],
112+
"capabilities": ["autocomplete", "chat"],
113113
"category": "balanced",
114114
"status": "deprecated",
115115
"tier": "free",
@@ -119,11 +119,39 @@
119119
}
120120
},
121121
{
122-
"modelId": "unknown",
122+
"modelId": "gemini-1.5-pro-latest",
123+
"modelRef": "google::v1::gemini-1.5-pro-latest",
124+
"displayName": "Gemini 1.5 Pro",
125+
"string": "gemini-1.5-pro-latest",
126+
"capabilities": ["autocomplete", "chat"],
127+
"category": "accuracy",
128+
"status": "stable",
129+
"tier": "pro",
130+
"contextWindow": {
131+
"maxInputTokens": 30000,
132+
"maxOutputTokens": 4000
133+
}
134+
},
135+
{
136+
"modelId": "gemini-1.5-flash-latest",
137+
"modelRef": "google::v1::gemini-1.5-flash-latest",
138+
"displayName": "Gemini 1.5 Flash",
139+
"string": "google/gemini-1.5-flash-latest",
140+
"capabilities": ["autocomplete", "chat"],
141+
"category": "speed",
142+
"status": "stable",
143+
"tier": "pro",
144+
"contextWindow": {
145+
"maxInputTokens": 30000,
146+
"maxOutputTokens": 4000
147+
}
148+
},
149+
{
150+
"modelId": "mixtral-8x7b-instruct",
123151
"modelRef": "mistral::v1::mixtral-8x7b-instruct",
124152
"displayName": "Mixtral 8x7B",
125153
"string": "mixtral-8x7b-instruct",
126-
"capabilities": ["chat", "edit"],
154+
"capabilities": ["autocomplete", "chat"],
127155
"category": "speed",
128156
"status": "stable",
129157
"tier": "pro",
@@ -133,11 +161,11 @@
133161
}
134162
},
135163
{
136-
"modelId": "unknown",
164+
"modelId": "mixtral-8x22b-instruct",
137165
"modelRef": "mistral::v1::mixtral-8x22b-instruct",
138166
"displayName": "Mixtral 8x22B",
139167
"string": "mixtral-8x22b-instruct",
140-
"capabilities": ["chat", "edit"],
168+
"capabilities": ["autocomplete", "chat"],
141169
"category": "accuracy",
142170
"status": "stable",
143171
"tier": "pro",
@@ -147,11 +175,11 @@
147175
}
148176
},
149177
{
150-
"modelId": "unknown",
178+
"modelId": "gpt-4o",
151179
"modelRef": "openai::2024-02-01::gpt-4o",
152180
"displayName": "GPT-4o",
153181
"string": "gpt-4o",
154-
"capabilities": ["chat", "edit"],
182+
"capabilities": ["autocomplete", "chat"],
155183
"category": "accuracy",
156184
"status": "stable",
157185
"tier": "pro",
@@ -161,12 +189,12 @@
161189
}
162190
},
163191
{
164-
"modelId": "unknown",
192+
"modelId": "gpt-4-turbo",
165193
"modelRef": "openai::2024-02-01::gpt-4-turbo",
166194
"displayName": "GPT-4 Turbo",
167195
"string": "gpt-4-turbo",
168-
"capabilities": ["chat", "edit"],
169-
"category": "accuracy",
196+
"capabilities": ["autocomplete", "chat"],
197+
"category": "balanced",
170198
"status": "stable",
171199
"tier": "pro",
172200
"contextWindow": {
@@ -175,11 +203,11 @@
175203
}
176204
},
177205
{
178-
"modelId": "unknown",
206+
"modelId": "gpt-3.5-turbo",
179207
"modelRef": "openai::2024-02-01::gpt-3.5-turbo",
180208
"displayName": "GPT-3.5 Turbo",
181209
"string": "gpt-3.5-turbo",
182-
"capabilities": ["chat", "edit"],
210+
"capabilities": ["autocomplete", "chat"],
183211
"category": "speed",
184212
"status": "stable",
185213
"tier": "pro",

internal/modelconfig/validation.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616

1717
// resourceIDRE is a regular expression for verifying resource IDs are
1818
// of a simple format.
19-
var resourceIDRE = regexp.MustCompile(`[a-z][a-z-]*[a-z]`)
19+
var resourceIDRE = regexp.MustCompile(`^[a-z0-9][a-z0-9_\-\.]*[a-z0-9]$`)
2020

2121
func validateProvider(p types.Provider) error {
2222
if l := len(p.DisplayName); l < 5 || l > 40 {
@@ -36,17 +36,23 @@ func validateProvider(p types.Provider) error {
3636
func validateModelRef(ref types.ModelRef) error {
3737
parts := strings.Split(string(ref), "::")
3838
if len(parts) != 3 {
39-
return errors.New("invalid number of parts")
39+
return errors.New("modelRef syntax error")
4040
}
4141
if !resourceIDRE.MatchString(parts[0]) {
4242
return errors.New("invalid ProviderID")
4343
}
44+
if !resourceIDRE.MatchString(parts[2]) {
45+
return errors.New("invalid ModelID")
46+
}
4447
// We don't impose any constraints on the API Version ID, because
4548
// while it's something Sourcegraph manages, there are lots of exotic
4649
// but reasonable forms it could take. e.g. "2024-06-01" or
4750
// "v1+beta2/with-git-lfs-context-support".
48-
if !resourceIDRE.MatchString(parts[2]) {
49-
return errors.New("invalid ModelID")
51+
//
52+
// But we still want to impose some basic standards, defined here.
53+
apiVersion := parts[1]
54+
if strings.ContainsAny(apiVersion, `:;*% $#\"',!@`) {
55+
return errors.New("invalid APIVersionID")
5056
}
5157

5258
return nil

internal/modelconfig/validation_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,61 @@ import (
1111
"github.com/sourcegraph/sourcegraph/internal/modelconfig/types"
1212
)
1313

14+
// Tests for various corner cases and regressions.
15+
func TestValidationMethods(t *testing.T) {
16+
t.Run("ValidateModelRef", func(t *testing.T) {
17+
tests := []struct {
18+
MRef string
19+
// WantErr is the text of the expected error message.
20+
// If empty, we expect no error.
21+
WantErr string
22+
}{
23+
// Valid MRefs.
24+
{"foo::bar::baz", ""},
25+
{"foo-dashed::bar-dashed::baz-dashed-twice", ""},
26+
{"foo.dotted::bar.dotted::baz.dotted.twice", ""},
27+
{"provider_id::api_id::model_id", ""},
28+
29+
{"provider::api-version-can-totally/have-slashes::model", ""},
30+
31+
{"anthropic::2023-06-01::claude-3.5-sonnet", ""},
32+
33+
// Expected failure with older-style model references.
34+
{"claude-2", "modelRef syntax error"},
35+
{"anthropic/claude-2", "modelRef syntax error"},
36+
37+
// Generic validation errors.
38+
{"a::b::c::d", "modelRef syntax error"},
39+
40+
{"provider/v1::api-version::model", "invalid ProviderID"},
41+
{"CAPS_PROVIDER::v1::model", "invalid ProviderID"},
42+
{"g o o g l e::v1::gemini-1.5", "invalid ProviderID"},
43+
44+
{"foo::name-with!exclamatnions-should::be-ok", "invalid APIVersionID"},
45+
{"google::version one::gemini-1.5", "invalid APIVersionID"},
46+
47+
{"provider::api-version::model/v1", "invalid ModelID"},
48+
{"provider::apiver::CAPS_MODEL", "invalid ModelID"},
49+
{"anthropic::2023-01-01::claude instant", "invalid ModelID"},
50+
{"google::v1::Gemini 1.5", "invalid ModelID"},
51+
}
52+
53+
for _, test := range tests {
54+
ref := types.ModelRef(test.MRef)
55+
gotErr := validateModelRef(ref)
56+
57+
var gotErrText string
58+
if gotErr != nil {
59+
gotErrText = gotErr.Error()
60+
}
61+
62+
assert.Equal(
63+
t, test.WantErr, gotErrText,
64+
"didn't get expected validation error for mref %q", test.MRef)
65+
}
66+
})
67+
}
68+
1469
// Confirm that the model data currently in the repo is well-formed and valid.
1570
func TestEmbeddedModelConfig(t *testing.T) {
1671
loadModelConfig := func(t *testing.T) types.ModelConfiguration {

0 commit comments

Comments
 (0)