Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.compose
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
REACT_APP_NODE_ENV=development
REACT_APP_LOCAL=localhost
REACT_APP_MODEL_SERVICE=model
REACT_APP_SERVER_PORT=5002
4 changes: 4 additions & 0 deletions .env.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
REACT_APP_NODE_ENV=development
REACT_APP_LOCAL=localhost
REACT_APP_MODEL_SERVICE=localhost
REACT_APP_SERVER_PORT=5002
9 changes: 4 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ ARG NODE_VERSION=23.10.0

FROM node:${NODE_VERSION}-alpine

# Use production node environment by default.
ENV NODE_ENV production


WORKDIR /usr/src/app

# Download dependencies as a separate step to take advantage of Docker's caching.
Expand All @@ -37,5 +33,8 @@ EXPOSE 3000
# To access server.js
EXPOSE 5001

# Expose dev port
EXPOSE 5002

# Run the application.
CMD npm start
CMD npm run start:prod
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ It is a NodeJS app that uses the llama3.2 model to service prompt requests. It u
## How to Run

### Locally
- Update the `App.js` and `server.js` to use 0.0.0.0 as hosts for API requests instead of K8s service names.
- `docker run -p 11434:11434 ollama/ollama:0.6.2`
- Run an LLM container `docker run -p 11434:11434 --name model ollama/ollama:0.6.2`
- Exec into the container and run `ollama pull llama3.2`
- `npm start`
- `dotenv -e .env.dev -- npm run start:dev`

### Locally with Docker Compose
I used compose to develop this locally.

- Update the `App.js` and `server.js` to use 0.0.0.0 as hosts for API requests instead of K8s service names.
- `docker compose up --build`
- When done, `docker compose down`

Expand Down
47 changes: 9 additions & 38 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,24 @@
# https://github.com/docker/awesome-compose
services:
server:
container_name: server
command: npm run start:dev
depends_on:
- model
build:
context: .
environment:
NODE_ENV: production
volumes:
- ./:/usr/src/app
- /usr/src/app/node_modules
env_file:
- .env.compose
ports:
- 3000:3000
- 5002:5002
model:
container_name: model
image: ollama/ollama:0.6.2
ports:
- 11434:11434
container_name: ollama
post_start:
- command: ollama pull llama3.2


# The commented out section below is an example of how to define a PostgreSQL
# database that your application can use. `depends_on` tells Docker Compose to
# start the database before your application. The `db-data` volume persists the
# database data between container restarts. The `db-password` secret is used
# to set the database password. You must create `db/password.txt` and add
# a password of your choosing to it before running `docker-compose up`.
# depends_on:
# db:
# condition: service_healthy
# db:
# image: postgres
# restart: always
# user: postgres
# secrets:
# - db-password
# volumes:
# - db-data:/var/lib/postgresql/data
# environment:
# - POSTGRES_DB=example
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
# expose:
# - 5432
# healthcheck:
# test: [ "CMD", "pg_isready" ]
# interval: 10s
# timeout: 5s
# retries: 5
# volumes:
# db-data:
# secrets:
# db-password:
# file: db/password.txt

28 changes: 24 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@
"concurrently": "^9.1.2",
"cors": "^2.8.5",
"dockerode": "^4.0.4",
"dotenv": "^16.4.7",
"node-polyfill-webpack-plugin": "^4.1.0",
"os": "^0.1.2",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "concurrently \"node server.js\" \"react-scripts start\"",
"start:prod": "concurrently \"node server.js\" \"react-scripts start\"",
"start:dev": "concurrently \"node server.js\" \"react-scripts start\"",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
Expand Down
16 changes: 6 additions & 10 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ const cors = require("cors"); // Import CORS middleware
const axios = require("axios")
const app = express(); // Initialize Express

// Use env variable, or fallback to localhost
// const LLM_API_HOST = process.env.LLM_API_HOST || 'http://0.0.0.0:11434';

app.use(cors());
app.use(express.json());

Expand All @@ -26,9 +23,8 @@ app.post("/execute", async (req, res) => {
});

function getResponse(model, prompt) {
//console.log(`${LLM_API_HOST}`)
// Use K8s service nae, switch back to 0.0.0.0 for local testing (npm start)
return axios.post("http://model-published:11434/api/generate", {
var host = ("REACT_APP_MODEL_SERVICE" in process.env) ? process.env.REACT_APP_MODEL_SERVICE : "model-published";
return axios.post(`http://${host}:11434/api/generate`, {
model: model,
prompt: prompt,
stream: false
Expand All @@ -43,8 +39,8 @@ function getResponse(model, prompt) {
});
}

// Start the server and listen on port 5001
const PORT = 5001;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
// Start the server and listen on port specified in command line, ex. PORT=5001 node server.js
var port = ("REACT_APP_SERVER_PORT" in process.env) ? process.env.REACT_APP_SERVER_PORT : 5001;
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
5 changes: 3 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ function App() {
const prompt = `Context: This is a cat named ${catName}. They have the following traits: ${catTraits}. Generate a response as the cat to the following message: ${newUserInput}`;

// Execute command and wait for the result
// Switch K8s service name to 0.0.0.0 for local testing!
const result = await fetch("http://a4c423481a99842669d9088bba7450ad-1853516926.us-east-2.elb.amazonaws.com:5001/execute", {
var host = ("REACT_APP_LOCAL" in process.env) ? process.env.REACT_APP_LOCAL : "a4c423481a99842669d9088bba7450ad-1853516926.us-east-2.elb.amazonaws.com";
var port = ("REACT_APP_SERVER_PORT" in process.env) ? process.env.REACT_APP_SERVER_PORT : 5001;
const result = await fetch(`http://${host}:${port}/execute`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
Expand Down