Skip to content

Commit 338da75

Browse files
committed
LLMをチャットから選択可能にする。クロスリージョン推論を東京リージョン、EUリージョンにも対応させる
1 parent c309e99 commit 338da75

File tree

8 files changed

+306
-74
lines changed

8 files changed

+306
-74
lines changed

electron.vite.config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ export default defineConfig({
1414
renderer: {
1515
resolve: {
1616
alias: {
17-
'@renderer': resolve('src/renderer/src')
17+
'@renderer': resolve('src/renderer/src'),
18+
'@': resolve('src')
1819
}
1920
},
2021
plugins: [

src/main/api/bedrock/models.ts

Lines changed: 131 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,169 @@
1-
import { LLM } from '../../../types/llm'
1+
import { BEDROCK_SUPPORTED_REGIONS, BedrockSupportRegion, LLM } from '../../../types/llm'
22

3-
export const models: LLM[] = [
3+
// Base models without cross-region inference
4+
export const baseModels: LLM[] = [
45
{
56
modelId: 'anthropic.claude-3-sonnet-20240229-v1:0',
67
modelName: 'Claude 3 Sonnet',
7-
toolUse: true
8+
toolUse: true,
9+
regions: BEDROCK_SUPPORTED_REGIONS
810
},
911
{
1012
modelId: 'anthropic.claude-3-haiku-20240307-v1:0',
1113
modelName: 'Claude 3 Haiku',
12-
toolUse: true
14+
toolUse: true,
15+
regions: BEDROCK_SUPPORTED_REGIONS
1316
},
1417
{
1518
modelId: 'anthropic.claude-3-5-haiku-20241022-v1:0',
1619
modelName: 'Claude 3.5 Haiku',
17-
toolUse: true
18-
},
19-
{
20-
modelId: 'us.anthropic.claude-3-5-haiku-20241022-v1:0',
21-
modelName: 'Claude 3.5 Haiku (cross region inference)',
22-
toolUse: true
20+
toolUse: true,
21+
regions: BEDROCK_SUPPORTED_REGIONS
2322
},
2423
{
2524
modelId: 'anthropic.claude-3-5-sonnet-20240620-v1:0',
2625
modelName: 'Claude 3.5 Sonnet',
27-
toolUse: true
28-
},
29-
{
30-
modelId: 'us.anthropic.claude-3-5-sonnet-20240620-v1:0',
31-
modelName: 'Claude 3.5 Sonnet (cross region inference)',
32-
toolUse: true
26+
toolUse: true,
27+
regions: BEDROCK_SUPPORTED_REGIONS
3328
},
3429
{
3530
modelId: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
3631
modelName: 'Claude 3.5 Sonnet v2',
37-
toolUse: true
32+
toolUse: true,
33+
regions: BEDROCK_SUPPORTED_REGIONS
34+
}
35+
]
36+
const usRegions = ['us-east-1', 'us-east-2', 'us-west-2'] as BedrockSupportRegion[]
37+
38+
// US cross-region inference models
39+
export const usModels: LLM[] = [
40+
{
41+
modelId: 'us.anthropic.claude-3-sonnet-20240229-v1:0',
42+
modelName: 'Claude 3 Sonnet (US cross-region)',
43+
toolUse: true,
44+
regions: ['us-east-1', 'us-west-2']
45+
},
46+
{
47+
modelId: 'us.anthropic.claude-3-haiku-20240307-v1:0',
48+
modelName: 'Claude 3 Haiku (US cross-region)',
49+
toolUse: true,
50+
regions: usRegions
51+
},
52+
{
53+
modelId: 'us.anthropic.claude-3-5-haiku-20241022-v1:0',
54+
modelName: 'Claude 3.5 Haiku (US cross-region)',
55+
toolUse: true,
56+
regions: usRegions
57+
},
58+
{
59+
modelId: 'us.anthropic.claude-3-5-sonnet-20240620-v1:0',
60+
modelName: 'Claude 3.5 Sonnet (US cross-region)',
61+
toolUse: true,
62+
regions: usRegions
3863
},
3964
{
4065
modelId: 'us.anthropic.claude-3-5-sonnet-20241022-v2:0',
41-
modelName: 'Claude 3.5 Sonnet v2 (cross region inference)',
42-
toolUse: true
66+
modelName: 'Claude 3.5 Sonnet v2 (US cross-region)',
67+
toolUse: true,
68+
regions: usRegions
4369
},
4470
{
4571
modelId: 'us.amazon.nova-pro-v1:0',
46-
modelName: 'Amazon Nova Pro (cross region inference)',
47-
toolUse: true
72+
modelName: 'Amazon Nova Pro (US cross-region)',
73+
toolUse: true,
74+
regions: usRegions
4875
},
4976
{
5077
modelId: 'us.amazon.nova-lite-v1:0',
51-
modelName: 'Amazon Nova Lite (cross region inference)',
52-
toolUse: true
78+
modelName: 'Amazon Nova Lite (US cross-region)',
79+
toolUse: true,
80+
regions: usRegions
5381
},
5482
{
5583
modelId: 'us.amazon.nova-micro-v1:0',
56-
modelName: 'Amazon Nova Micro (cross region inference)',
57-
toolUse: true
84+
modelName: 'Amazon Nova Micro (US cross-region)',
85+
toolUse: true,
86+
regions: usRegions
5887
}
5988
]
6089

90+
const euRegions = ['eu-central-1', 'eu-west-1', 'eu-west-3'] as BedrockSupportRegion[]
91+
92+
// EU cross-region inference models
93+
export const euModels: LLM[] = [
94+
{
95+
modelId: 'eu.anthropic.claude-3-sonnet-20240229-v1:0',
96+
modelName: 'Claude 3 Sonnet (EU cross-region)',
97+
toolUse: true,
98+
regions: euRegions
99+
},
100+
{
101+
modelId: 'eu.anthropic.claude-3-5-sonnet-20240620-v1:0',
102+
modelName: 'Claude 3.5 Sonnet (EU cross-region)',
103+
toolUse: true,
104+
regions: euRegions
105+
},
106+
{
107+
modelId: 'eu.anthropic.claude-3-haiku-20240307-v1:0',
108+
modelName: 'Claude 3 Haiku (EU cross-region)',
109+
toolUse: true,
110+
regions: euRegions
111+
}
112+
]
113+
114+
const apacRegions = [
115+
'ap-northeast-1',
116+
'ap-northeast-2',
117+
'ap-south-1',
118+
'ap-southeast-1',
119+
'ap-southeast-2'
120+
] as BedrockSupportRegion[]
121+
122+
// APAC cross-region inference models
123+
export const apacModels: LLM[] = [
124+
{
125+
modelId: 'apac.anthropic.claude-3-sonnet-20240229-v1:0',
126+
modelName: 'Claude 3 Sonnet (APAC cross-region)',
127+
toolUse: true,
128+
regions: apacRegions
129+
},
130+
{
131+
modelId: 'apac.anthropic.claude-3-5-sonnet-20240620-v1:0',
132+
modelName: 'Claude 3.5 Sonnet (APAC cross-region)',
133+
toolUse: true,
134+
regions: apacRegions
135+
},
136+
{
137+
modelId: 'apac.anthropic.claude-3-haiku-20240307-v1:0',
138+
modelName: 'Claude 3 Haiku (APAC cross-region)',
139+
toolUse: true,
140+
regions: apacRegions
141+
}
142+
]
143+
144+
// Combine all models based on region
145+
export const getModelsForRegion = (region: BedrockSupportRegion): LLM[] => {
146+
const models = [...baseModels]
147+
148+
// Add US models for US regions
149+
if (usRegions.includes(region)) {
150+
models.push(...usModels.filter((model) => model.regions?.includes(region)))
151+
}
152+
153+
// Add EU models for EU regions
154+
if (euRegions.includes(region)) {
155+
models.push(...euModels.filter((model) => model.regions?.includes(region)))
156+
}
157+
158+
// Add APAC models for APAC regions
159+
if (apacRegions.includes(region)) {
160+
models.push(...apacModels.filter((model) => model.regions?.includes(region)))
161+
}
162+
163+
return models
164+
}
165+
166+
// Prompt Router support
61167
export const getDefaultPromptRouter = (accountId: string, region: string) => {
62168
if (region === 'us-east-1' || region === 'us-west-2') {
63169
return [

src/main/api/bedrock/services/modelService.ts

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,13 @@
1-
import { ListFoundationModelsCommand } from '@aws-sdk/client-bedrock'
2-
import { getDefaultPromptRouter, models } from '../models'
3-
import { createBedrockClient } from '../client'
1+
import { getDefaultPromptRouter, getModelsForRegion } from '../models'
42
import { getAccountId } from '../utils/awsUtils'
5-
import type { LLM } from '../../../../types/llm'
6-
import type { AWSCredentials, ServiceContext } from '../types'
3+
import type { ServiceContext } from '../types'
74

85
export class ModelService {
96
private static readonly CACHE_LIFETIME = 1000 * 60 * 60 // 1 hour
107
private modelCache: { [key: string]: any } = {}
118

129
constructor(private context: ServiceContext) {}
1310

14-
private async listAvailableModels(credentials: AWSCredentials) {
15-
const client = createBedrockClient(credentials)
16-
const command = new ListFoundationModelsCommand({})
17-
18-
try {
19-
const response = await client.send(command)
20-
return (
21-
response.modelSummaries?.map((model) => ({
22-
modelId: model.modelId || '',
23-
modelName: model.modelName || ''
24-
})) || []
25-
)
26-
} catch (error) {
27-
console.error('Error listing foundation models:', error)
28-
return []
29-
}
30-
}
31-
3211
async listModels() {
3312
const credentials = this.context.store.get('aws')
3413
const { region, accessKeyId, secretAccessKey } = credentials
@@ -49,17 +28,11 @@ export class ModelService {
4928
}
5029

5130
try {
52-
const availableModels = await this.listAvailableModels(credentials)
53-
const availableModelIds = availableModels.map((model) => model.modelId)
54-
const filteredModels = models.filter(
55-
(model: LLM) =>
56-
availableModelIds.includes(model.modelId) ||
57-
availableModelIds.includes(model.modelId.slice(3))
58-
)
31+
const models = getModelsForRegion(region)
5932

6033
const accountId = await getAccountId(credentials)
6134
const promptRouterModels = accountId ? getDefaultPromptRouter(accountId, region) : []
62-
const result = [...filteredModels, ...promptRouterModels]
35+
const result = [...models, ...promptRouterModels]
6336
this.modelCache[cacheKey] = [...result, { _timestamp: Date.now() } as any]
6437

6538
return result

src/renderer/src/contexts/SettingsContext.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React, { createContext, useContext, useState, useEffect, useMemo, useCallback } from 'react'
22
import { Agent, KnowledgeBase, Scenario, SendMsgKey, ToolState } from 'src/types/agent-chat'
3-
import { InferenceParameters, LLM } from 'src/types/llm'
43
import { listModels } from '@renderer/lib/api'
54
import { CustomAgent } from '@/types/agent-chat'
65
import { Tool } from '@aws-sdk/client-bedrock-runtime'
@@ -12,6 +11,7 @@ import {
1211
CODE_BUDDY_SYSTEM_PROMPT,
1312
PRODUCT_DESIGNER_SYSTEM_PROMPT
1413
} from '@renderer/pages/ChatPage/constants/DEFAULT_AGENTS'
14+
import { InferenceParameters, LLM, BEDROCK_SUPPORTED_REGIONS } from '@/types/llm'
1515

1616
const DEFAULT_INFERENCE_PARAMS: InferenceParameters = {
1717
maxTokens: 4096,
@@ -166,9 +166,10 @@ export const SettingsProvider: React.FC<{ children: React.ReactNode }> = ({ chil
166166
// LLM Settings
167167
const [llmError, setLLMError] = useState<any>()
168168
const defaultModel = {
169-
modelId: 'us.anthropic.claude-3-5-sonnet-20241022-v2:0',
170-
modelName: 'Claude 3.5 Sonnet v2 (cross region inference)',
171-
toolUse: true
169+
modelId: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
170+
modelName: 'Claude 3.5 Sonnet v2',
171+
toolUse: true,
172+
regions: BEDROCK_SUPPORTED_REGIONS
172173
}
173174
const [currentLLM, setCurrentLLM] = useState<LLM>(defaultModel)
174175
const [availableModels, setAvailableModels] = useState<LLM[]>([])

src/renderer/src/pages/ChatPage/components/InputForm/index.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ToolSettings } from './ToolSettings'
44
import { DirectorySelector } from './DirectorySelector'
55
import { SendMsgKey } from '@/types/agent-chat'
66
import { FiTrash2 } from 'react-icons/fi'
7+
import { ModelSelector } from '../ModelSelector'
78

89
type InputFormProps = {
910
userInput: string
@@ -35,12 +36,15 @@ export const InputForm: React.FC<InputFormProps> = ({
3536
const [isComposing, setIsComposing] = useState(false)
3637

3738
return (
38-
<div className="flex gap-2 fixed bottom-0 left-20 right-5 bottom-3">
39+
<div className="flex gap-2 fixed bottom-0 left-20 right-5 bottom-3 pt-3">
3940
<div className="relative w-full">
4041
<div className="flex justify-between mb-2">
4142
{/* left */}
4243
<div className="flex flex-col justify-end gap-2 mb-1">
43-
<ToolSettings onOpenToolSettings={onOpenToolSettings} />
44+
<div className="flex gap-2">
45+
<ToolSettings onOpenToolSettings={onOpenToolSettings} />
46+
<ModelSelector openable={true} />
47+
</div>
4448
<DirectorySelector
4549
projectPath={projectPath}
4650
onSelectDirectory={onSelectDirectory}

0 commit comments

Comments
 (0)