-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat frontend api refactor #24
Changes from 14 commits
47bf8ff
bb7478a
7f7a682
2fd07ab
ff0011c
7afa251
ac9c5a2
a034248
666d159
ffbe0dd
9c1924e
d90bf48
72209ba
4902e36
2314719
f2575a3
42c7a88
652c9b5
73a810d
ce340f5
806894b
3729eb7
bb28f69
ff17f54
d07ef4c
fb4319f
a2310f7
eb8ccca
d89f771
abd7b81
723a6e4
6279339
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"typescript.tsdk": "node_modules/typescript/lib", | ||
"typescript.enablePromptUseWorkspaceTsdk": true | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"cSpell.words": ["upsert"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,4 @@ Still on progress | |
|
||
CodeFox | ||
LOGO | ||
 | ||
 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,13 +5,13 @@ | |
import { join } from 'path'; | ||
import { TypeOrmModule } from '@nestjs/typeorm'; | ||
import { UserModule } from './user/user.module'; | ||
import { User } from './user/user.model'; | ||
Check warning on line 8 in backend/src/app.module.ts
|
||
import { AuthModule } from './auth/auth.module'; | ||
import { ProjectModule } from './project/project.module'; | ||
import { TokenModule } from './token/token.module'; | ||
import { ConfigModule, ConfigService } from '@nestjs/config'; | ||
Check warning on line 12 in backend/src/app.module.ts
|
||
import { JwtModule } from '@nestjs/jwt'; | ||
Check warning on line 13 in backend/src/app.module.ts
|
||
import { JwtCacheService } from './auth/jwt-cache.service'; | ||
Check warning on line 14 in backend/src/app.module.ts
|
||
import { ChatModule } from './chat/chat.module'; | ||
|
||
@Module({ | ||
|
@@ -19,7 +19,7 @@ | |
ConfigModule.forRoot({ isGlobal: true }), | ||
GraphQLModule.forRoot<ApolloDriverConfig>({ | ||
driver: ApolloDriver, | ||
autoSchemaFile: join(process.cwd(), 'src/schema.gql'), | ||
autoSchemaFile: join(process.cwd(), '../frontend/src/graphql/schema.gql'), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Schema file location creates deployment risks and tight coupling The verification confirms the architectural concerns. The only cross-directory reference is the schema path in
Recommended solution: - autoSchemaFile: join(process.cwd(), '../frontend/src/graphql/schema.gql'),
+ autoSchemaFile: join(process.cwd(), 'src/schema.gql'), Then implement one of these approaches:
🔗 Analysis chainConsider architectural implications of schema location. Moving the GraphQL schema file to the frontend directory creates a tight coupling between backend and frontend, which could lead to deployment and build issues. This approach:
Consider these alternatives:
- autoSchemaFile: join(process.cwd(), '../frontend/src/graphql/schema.gql'),
+ autoSchemaFile: join(process.cwd(), 'src/schema.gql'), Then add a build step to copy the schema to frontend.
- autoSchemaFile: join(process.cwd(), '../frontend/src/graphql/schema.gql'),
+ autoSchemaFile: join(process.cwd(), '../shared/schema.gql'),
Let's verify the potential impact: 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Check if there are any direct imports or references between frontend and backend
rg -g '!node_modules' -l 'frontend|backend' backend/
Length of output: 130 Script: #!/bin/bash
# Let's check the content of these files to understand the nature of frontend/backend references
echo "=== app.module.ts ==="
cat backend/src/app.module.ts
echo -e "\n=== protocol.ts ==="
cat backend/src/chat/protocol.ts
echo -e "\n=== package.json ==="
cat backend/package.json
Length of output: 8602 |
||
sortSchema: true, | ||
playground: true, | ||
installSubscriptionHandlers: true, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ class ChatCompletionDelta { | |
@Field({ nullable: true }) | ||
content?: string; | ||
} | ||
|
||
@ObjectType('ChatCompletionChunkType') | ||
export class ChatCompletionChunk { | ||
@Field() | ||
|
@@ -20,7 +21,7 @@ export class ChatCompletionChunk { | |
model: string; | ||
|
||
@Field({ nullable: true }) | ||
system_fingerprint: string | null; | ||
systemFingerprint: string | null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Update required: Inconsistent field naming across the codebase The field rename from
While the model and frontend use camelCase, protocol files still use snake_case, which needs to be synchronized. 🔗 Analysis chainVerify the impact of the systemFingerprint rename. The field rename from Also applies to: 88-90 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Search for any remaining snake_case usage of system_fingerprint
rg -l "system_fingerprint" --type ts --type tsx
# Search for GraphQL queries/mutations using the old field name
rg -l "system_fingerprint" --type graphql
Length of output: 149 Script: #!/bin/bash
# Search for any remaining snake_case usage of system_fingerprint in all files
rg "system_fingerprint"
# Search for camelCase usage to understand the context
rg "systemFingerprint"
Length of output: 666 |
||
|
||
@Field(() => [ChatCompletionChoice]) | ||
choices: ChatCompletionChoice[]; | ||
|
@@ -35,7 +36,7 @@ class ChatCompletionChoice { | |
delta: ChatCompletionDelta; | ||
|
||
@Field({ nullable: true }) | ||
finish_reason: string | null; | ||
finishReason: string | null; | ||
} | ||
|
||
@InputType('ChatInputType') | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -4,6 +4,18 @@ import 'reflect-metadata'; | |||||||||||||||||||||||||
|
||||||||||||||||||||||||||
async function bootstrap() { | ||||||||||||||||||||||||||
const app = await NestFactory.create(AppModule); | ||||||||||||||||||||||||||
app.enableCors({ | ||||||||||||||||||||||||||
origin: '*', | ||||||||||||||||||||||||||
credentials: true, | ||||||||||||||||||||||||||
Comment on lines
+8
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Fix invalid CORS configuration The combination of If this is for development, consider: - origin: '*',
+ origin: process.env.NODE_ENV === 'production'
+ ? 'https://your-production-domain.com'
+ : 'http://localhost:3001', // adjust port as needed If you need to support multiple origins: - origin: '*',
+ origin: process.env.NODE_ENV === 'production'
+ ? ['https://domain1.com', 'https://domain2.com']
+ : 'http://localhost:3001',
|
||||||||||||||||||||||||||
methods: ['GET', 'POST', 'OPTIONS'], | ||||||||||||||||||||||||||
allowedHeaders: [ | ||||||||||||||||||||||||||
'Content-Type', | ||||||||||||||||||||||||||
'Accept', | ||||||||||||||||||||||||||
'Authorization', | ||||||||||||||||||||||||||
'Access-Control-Allow-Origin', | ||||||||||||||||||||||||||
'Access-Control-Allow-Credentials', | ||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||
Comment on lines
+11
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unnecessary CORS headers from allowedHeaders The Apply this fix: allowedHeaders: [
'Content-Type',
'Accept',
'Authorization',
- 'Access-Control-Allow-Origin',
- 'Access-Control-Allow-Credentials',
], 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||
await app.listen(process.env.PORT ?? 3000); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
bootstrap(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
"extends": "next/core-web-vitals", | ||
"ignorePatterns": ["src/graphql/type.ts", "src/graphql/**/*"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
name: frontend-dev | ||
root: ./ | ||
|
||
windows: | ||
- editor: | ||
layout: even-horizontal | ||
panes: | ||
- next: | ||
- pnpm dev | ||
- codegen: | ||
- pnpm generate:watch |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,134 +1 @@ | ||
<div align="center"> | ||
<img src="ollama-nextjs-ui.gif"> | ||
</div> | ||
|
||
<h1 align="center"> | ||
Fully-featured & beautiful web interface for Ollama LLMs | ||
</h1> | ||
|
||
<div align="center"> | ||
|
||
 | ||
|
||
</div> | ||
|
||
Get up and running with Large Language Models **quickly**, **locally** and even **offline**. | ||
This project aims to be the easiest way for you to get started with LLMs. No tedious and annoying setup required! | ||
|
||
# Features ✨ | ||
|
||
- **Beautiful & intuitive UI:** Inspired by ChatGPT, to enhance similarity in the user experience. | ||
- **Fully local:** Stores chats in localstorage for convenience. No need to run a database. | ||
- **Fully responsive:** Use your phone to chat, with the same ease as on desktop. | ||
- **Easy setup:** No tedious and annoying setup required. Just clone the repo and you're good to go! | ||
- **Code syntax highligting:** Messages that include code, will be highlighted for easy access. | ||
- **Copy codeblocks easily:** Easily copy the highlighted code with one click. | ||
- **Download/Pull & Delete models:** Easily download and delete models directly from the interface. | ||
- **Switch between models:** Switch between models fast with a click. | ||
- **Chat history:** Chats are saved and easily accessed. | ||
- **Light & Dark mode:** Switch between light & dark mode. | ||
|
||
# Preview | ||
|
||
https://github.com/jakobhoeg/nextjs-ollama-llm-ui/assets/114422072/08eaed4f-9deb-4e1b-b87a-ba17d81b9a02 | ||
|
||
# Requisites ⚙️ | ||
|
||
To use the web interface, these requisites must be met: | ||
|
||
1. Download [Ollama](https://ollama.com/download) and have it running. Or run it in a Docker container. Check the [docs](https://github.com/ollama/ollama) for instructions. | ||
2. Node.js (18+) and npm is required. [Download](https://nodejs.org/en/download) | ||
|
||
# Deploy your own to Vercel or Netlify in one click ✨ | ||
|
||
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fjakobhoeg%2Fnextjs-ollama-llm-ui&env=NEXT_PUBLIC_OLLAMA_URL&envDescription=Your%20Ollama%20URL) [](https://app.netlify.com/start/deploy?repository=https://github.com/jakobhoeg/nextjs-ollama-llm-ui) | ||
|
||
You'll need to set your [OLLAMA_ORIGINS](https://github.com/ollama/ollama/blob/main/docs/faq.md) environment variable on your machine that is running Ollama: | ||
|
||
``` | ||
OLLAMA_ORIGINS="https://your-app.vercel.app/" | ||
``` | ||
|
||
# Installation 📖 | ||
|
||
[](https://repology.org/project/nextjs-ollama-llm-ui/versions) | ||
|
||
Use a pre-build package from one of the supported package managers to run a local environment of the web interface. | ||
Alternatively you can install from source with the instructions below. | ||
|
||
> [!NOTE] | ||
> If your frontend runs on something other than `http://localhost` or `http://127.0.0.1`, you'll need to set the OLLAMA_ORIGINS to your frontend url. | ||
> | ||
> This is also stated in the [documentation](https://github.com/ollama/ollama/blob/main/docs/faq.md#how-do-i-configure-ollama-server): | ||
> | ||
> `Ollama allows cross-origin requests from 127.0.0.1 and 0.0.0.0 by default. Additional origins can be configured with OLLAMA_ORIGINS` | ||
|
||
## Install from source | ||
|
||
**1. Clone the repository to a directory on your pc via command prompt:** | ||
|
||
``` | ||
git clone https://github.com/jakobhoeg/nextjs-ollama-llm-ui | ||
``` | ||
|
||
**2. Open the folder:** | ||
|
||
``` | ||
cd nextjs-ollama-llm-ui | ||
``` | ||
|
||
**3. Rename the `.example.env` to `.env`:** | ||
|
||
``` | ||
mv .example.env .env | ||
``` | ||
|
||
**4. If your instance of Ollama is NOT running on the default ip-address and port, change the variable in the .env file to fit your usecase:** | ||
|
||
``` | ||
NEXT_PUBLIC_OLLAMA_URL="http://localhost:11434" | ||
``` | ||
|
||
**5. Install dependencies:** | ||
|
||
``` | ||
npm install | ||
``` | ||
|
||
**6. Start the development server:** | ||
|
||
``` | ||
npm run dev | ||
``` | ||
|
||
**5. Go to [localhost:3000](http://localhost:3000) and start chatting with your favourite model!** | ||
|
||
# Upcoming features | ||
|
||
This is a to-do list consisting of upcoming features. | ||
|
||
- ✅ Voice input support | ||
- ✅ Code syntax highlighting | ||
- ✅ Ability to send an image in the prompt to utilize vision language models. | ||
- ✅ Ability to regenerate responses | ||
- ⬜️ Import and export chats | ||
|
||
# Tech stack | ||
|
||
[NextJS](https://nextjs.org/) - React Framework for the Web | ||
|
||
[TailwindCSS](https://tailwindcss.com/) - Utility-first CSS framework | ||
|
||
[shadcn-ui](https://ui.shadcn.com/) - UI component built using Radix UI and Tailwind CSS | ||
|
||
[shadcn-chat](https://github.com/jakobhoeg/shadcn-chat) - Chat components for NextJS/React projects | ||
|
||
[Framer Motion](https://www.framer.com/motion/) - Motion/animation library for React | ||
|
||
[Lucide Icons](https://lucide.dev/) - Icon library | ||
|
||
# Helpful links | ||
|
||
[Medium Article](https://medium.com/@bartek.lewicz/launch-your-own-chatgpt-clone-for-free-on-colab-shareable-and-online-in-less-than-10-minutes-da19e44be5eb) - How to launch your own ChatGPT clone for free on Google Colab. By Bartek Lewicz. | ||
|
||
[Lobehub mention](https://lobehub.com/blog/5-ollama-web-ui-recommendation#5-next-js-ollama-llm-ui) - Five Excellent Free Ollama WebUI Client Recommendations | ||
- we are using tmuxinator if you want to watch both codegen and dev server |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { CodegenConfig } from '@graphql-codegen/cli'; | ||
|
||
const config: CodegenConfig = { | ||
schema: './src/graphql/schema.gql', | ||
generates: { | ||
'src/graphql/type.tsx': { | ||
plugins: [ | ||
'typescript', | ||
'typescript-operations', | ||
'typescript-resolvers', | ||
'typescript-react-apollo', | ||
], | ||
config: { | ||
withHooks: true, | ||
useIndexSignature: true, | ||
enumsAsTypes: true, | ||
constEnums: true, | ||
skipTypename: false, | ||
dedupeOperationSuffix: true, | ||
nonOptionalTypename: true, | ||
preResolveTypes: true, | ||
namingConvention: { | ||
enumValues: 'keep', | ||
}, | ||
scalars: { | ||
Date: 'Date', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
export default config; |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -5,10 +5,13 @@ | |||
"scripts": { | ||||
"dev": "next dev", | ||||
"start:dev": "next dev", | ||||
"start:dev-watch": "tmuxinator start -p .tmuxinator/build.yml", | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Missing tmuxinator configuration file for development setup The script
🔗 Analysis chainLGTM! Verify tmuxinator configuration. The new scripts enhance the development workflow with GraphQL code generation support. The tmuxinator integration is a good addition for managing multiple development processes. Let's verify the tmuxinator configuration exists: Also applies to: 12-14 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Verify tmuxinator configuration file exists
if [ -f ".tmuxinator/build.yml" ]; then
echo "Tmuxinator config found"
cat ".tmuxinator/build.yml"
else
echo "Warning: Missing tmuxinator configuration at .tmuxinator/build.yml"
fi
Length of output: 177 |
||||
"build": "next build", | ||||
"start": "next start", | ||||
"lint": "next lint --fix", | ||||
"format": "prettier --write \"src/**/*.ts\"" | ||||
"format": "prettier --write \"src/**/*.ts\"", | ||||
"generate": "graphql-codegen", | ||||
"generate:watch": "graphql-codegen --watch" | ||||
}, | ||||
"dependencies": { | ||||
"@apollo/client": "^3.11.8", | ||||
|
@@ -17,6 +20,7 @@ | |||
"@hookform/resolvers": "^3.9.0", | ||||
"@langchain/community": "^0.3.1", | ||||
"@langchain/core": "^0.3.3", | ||||
"@nestjs/common": "^10.4.6", | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unnecessary backend dependency.
- "@nestjs/common": "^10.4.6", 📝 Committable suggestion
Suggested change
|
||||
"@radix-ui/react-avatar": "^1.1.0", | ||||
"@radix-ui/react-dialog": "^1.1.1", | ||||
"@radix-ui/react-dropdown-menu": "^2.1.1", | ||||
|
@@ -28,17 +32,14 @@ | |||
"@radix-ui/react-slot": "^1.1.0", | ||||
"@radix-ui/react-tooltip": "^1.1.2", | ||||
"@types/dom-speech-recognition": "^0.0.4", | ||||
"ai": "^3.4.0", | ||||
"class-variance-authority": "^0.7.0", | ||||
"clsx": "^2.1.1", | ||||
"emoji-mart": "^5.6.0", | ||||
"framer-motion": "^11.5.6", | ||||
"graphql": "^16.9.0", | ||||
"langchain": "^0.3.2", | ||||
"lucide-react": "^0.445.0", | ||||
"next": "^14.2.13", | ||||
"next-themes": "^0.3.0", | ||||
"ollama-ai-provider": "^0.15.0", | ||||
"react": "^18.3.1", | ||||
"react-code-blocks": "^0.1.6", | ||||
"react-dom": "^18.3.1", | ||||
|
@@ -57,6 +58,16 @@ | |||
"zustand": "^5.0.0-rc.2" | ||||
}, | ||||
"devDependencies": { | ||||
"@0no-co/graphqlsp": "^1.12.16", | ||||
"@graphql-codegen/cli": "^5.0.3", | ||||
"@graphql-codegen/typescript": "^4.1.0", | ||||
"@graphql-codegen/typescript-operations": "^4.3.0", | ||||
"@graphql-codegen/typescript-react-apollo": "^4.3.2", | ||||
"@graphql-codegen/typescript-resolvers": "^4.3.0", | ||||
"@parcel/watcher": "^2.4.1", | ||||
"@testing-library/dom": "^10.4.0", | ||||
"@testing-library/jest-dom": "^6.6.2", | ||||
"@testing-library/react": "^16.0.1", | ||||
"@types/jest": "^29.5.14", | ||||
"@types/node": "^22.5.5", | ||||
"@types/react": "^18.3.8", | ||||
|
@@ -66,9 +77,11 @@ | |||
"eslint": "8.57.1", | ||||
"eslint-config-next": "14.2.13", | ||||
"jest": "^29.7.0", | ||||
"jest-environment-jsdom": "^29.7.0", | ||||
"postcss": "^8.4.47", | ||||
"tailwindcss": "^3.4.12", | ||||
"ts-jest": "^29.2.5", | ||||
"ts-node": "^10.9.2", | ||||
"typescript": "^5.6.2" | ||||
} | ||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding explicit return types rule.
Since you're enhancing TypeScript support, consider also adding the
@typescript-eslint/explicit-function-return-type
rule to ensure all functions have explicit return types.📝 Committable suggestion