Skip to content

Commit e88fef0

Browse files
authored
Merge pull request #454 from miurla/feat/improve-model-config
refactor: improve model configuration management
2 parents 6e51236 + 94d0e9e commit e88fef0

File tree

8 files changed

+71
-22
lines changed

8 files changed

+71
-22
lines changed

README.md

+23
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,29 @@ Host your own live version of Morphic with Vercel, Cloudflare Pages, or Docker.
150150

151151
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fmiurla%2Fmorphic&env=OPENAI_API_KEY,TAVILY_API_KEY,UPSTASH_REDIS_REST_URL,UPSTASH_REDIS_REST_TOKEN)
152152

153+
### Docker Prebuilt Image
154+
155+
Prebuilt Docker images are available on GitHub Container Registry:
156+
157+
```bash
158+
docker pull ghcr.io/miurla/morphic:latest
159+
```
160+
161+
You can use it with docker-compose:
162+
163+
```yaml
164+
services:
165+
morphic:
166+
image: ghcr.io/miurla/morphic:latest
167+
env_file: .env.local
168+
ports:
169+
- '3000:3000'
170+
volumes:
171+
- ./models.json:/app/public/config/models.json # Optional: Override default model configuration
172+
```
173+
174+
The default model configuration is located at `public/config/models.json`. For Docker deployment, you can create `models.json` alongside `.env.local` to override the default configuration.
175+
153176
## 🔎 Search Engine
154177

155178
### Setting up the Search Engine in Your Browser

app/page.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Chat } from '@/components/chat'
2-
import modelsList from '@/lib/config/models.json'
3-
import { Model } from '@/lib/types/models'
2+
import { getModels } from '@/lib/config/models'
43
import { generateId } from 'ai'
54

65
export default function Page() {
76
const id = generateId()
8-
return <Chat id={id} models={modelsList.models as Model[]} />
7+
const models = getModels()
8+
return <Chat id={id} models={models} />
99
}

app/search/[id]/page.tsx

+4-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Chat } from '@/components/chat'
22
import { getChat } from '@/lib/actions/chat'
3-
import modelsList from '@/lib/config/models.json'
4-
import { Model } from '@/lib/types/models'
3+
import { getModels } from '@/lib/config/models'
54
import { convertToUIMessages } from '@/lib/utils'
65
import { notFound, redirect } from 'next/navigation'
76

@@ -22,6 +21,7 @@ export default async function SearchPage(props: {
2221
}) {
2322
const userId = 'anonymous'
2423
const { id } = await props.params
24+
2525
const chat = await getChat(id, userId)
2626
// convertToUIMessages for useChat hook
2727
const messages = convertToUIMessages(chat?.messages || [])
@@ -34,11 +34,6 @@ export default async function SearchPage(props: {
3434
notFound()
3535
}
3636

37-
return (
38-
<Chat
39-
id={id}
40-
savedMessages={messages}
41-
models={modelsList.models as Model[]}
42-
/>
43-
)
37+
const models = getModels()
38+
return <Chat id={id} savedMessages={messages} models={models} />
4439
}

app/search/page.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Chat } from '@/components/chat'
2+
import { getModels } from '@/lib/config/models'
23
import { generateId } from 'ai'
34
import { redirect } from 'next/navigation'
45

@@ -13,5 +14,6 @@ export default async function SearchPage(props: {
1314
}
1415

1516
const id = generateId()
16-
return <Chat id={id} query={q} />
17+
const models = getModels()
18+
return <Chat id={id} query={q} models={models} />
1719
}

app/share/[id]/page.tsx

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Chat } from '@/components/chat'
22
import { getSharedChat } from '@/lib/actions/chat'
3-
import modelsList from '@/lib/config/models.json'
4-
import { Model } from '@/lib/types/models'
3+
import { getModels } from '@/lib/config/models'
54
import { convertToUIMessages } from '@/lib/utils'
65
import { notFound } from 'next/navigation'
76

@@ -25,18 +24,17 @@ export default async function SharePage(props: {
2524
}) {
2625
const { id } = await props.params
2726
const chat = await getSharedChat(id)
28-
// convertToUIMessages for useChat hook
29-
const messages = convertToUIMessages(chat?.messages || [])
3027

3128
if (!chat || !chat.sharePath) {
32-
notFound()
29+
return notFound()
3330
}
3431

32+
const models = getModels()
3533
return (
3634
<Chat
37-
id={id}
38-
savedMessages={messages}
39-
models={modelsList.models as Model[]}
35+
id={chat.id}
36+
savedMessages={convertToUIMessages(chat.messages)}
37+
models={models}
4038
/>
4139
)
4240
}

docs/CONFIGURATION.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ docker-compose logs searxng
121121

122122
## Additional AI Providers
123123

124-
Models are configured in `lib/config/models.json`. Each model requires its corresponding API key to be set in the environment variables.
124+
Models are configured in `public/config/models.json`. Each model requires its corresponding API key to be set in the environment variables.
125125

126126
### Model Configuration
127127

lib/config/models.ts

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Model } from '@/lib/types/models'
2+
import { existsSync, readFileSync } from 'fs'
3+
import { join } from 'path'
4+
5+
export function validateModel(model: any): model is Model {
6+
return (
7+
typeof model.id === 'string' &&
8+
typeof model.name === 'string' &&
9+
typeof model.provider === 'string' &&
10+
typeof model.providerId === 'string' &&
11+
typeof model.enabled === 'boolean' &&
12+
(model.toolCallType === 'native' || model.toolCallType === 'manual') &&
13+
(model.toolCallModel === undefined || typeof model.toolCallModel === 'string')
14+
)
15+
}
16+
17+
export function getModels(): Model[] {
18+
const configPath = join(process.cwd(), 'public', 'config', 'models.json')
19+
20+
try {
21+
const config = JSON.parse(readFileSync(configPath, 'utf-8'))
22+
if (Array.isArray(config.models) && config.models.every(validateModel)) {
23+
return config.models
24+
}
25+
console.warn('Invalid model configuration')
26+
} catch (error) {
27+
console.warn('Failed to load models:', error)
28+
}
29+
30+
return []
31+
}
File renamed without changes.

0 commit comments

Comments
 (0)