Skip to content

Commit

Permalink
Merge pull request #42 from Lumerin-protocol/main
Browse files Browse the repository at this point in the history
1.4.0 Update
  • Loading branch information
DavidAJohnston authored Dec 11, 2024
2 parents 5e8bd4e + 473a1eb commit 55ecaa8
Show file tree
Hide file tree
Showing 50 changed files with 1,390 additions and 255 deletions.
4 changes: 2 additions & 2 deletions .github/actions/gen_tag_name/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ runs:
VMIN=0
VPAT=0
set +o pipefail
VLAST=$(git describe --tags --abbrev=0 --match='v[1-9]*' 2>/dev/null | cut -c2-)
VLAST=$(git describe --tags --abbrev=0 --match='v[1-9]*' refs/remotes/origin/main 2>/dev/null | cut -c2-)
[ $VLAST ] && declare $(echo $VLAST | awk -F '.' '{print "VMAJ="$1" VMIN="$2" VPAT="$3}')
if [ "$GITHUB_REF_NAME" = "main" ]
then
VPAT=0
VMIN=$((VMIN+1))
VFULL=${VMAJ}.${VMIN}
VFULL=${VMAJ}.${VMIN}.${VPAT}
VTAG=v$VFULL
else
MB=$(git merge-base refs/remotes/origin/main HEAD)
Expand Down
26 changes: 20 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on:
branches:
- main
- test
- concom
- dev
paths: ['.github/workflows/**', '**/Makefile', '**/*.go', '**/*.json', '**/*.yml', '**/*.ts', '**/*.js']

Expand Down Expand Up @@ -72,6 +73,7 @@ jobs:
--form "ref=${{ env.gitlab_branch }}" \
--form "variables[SOURCE_REPO]=${{ github.repository }}" \
--form "variables[SOURCE_BRANCH]=${{ github.ref_name }}" \
--form "variables[GITHUB_VFULL]=${{ env.VFULL }}" \
--form "variables[GITHUB_TAG]=${{ env.TAG_NAME }}")

# Parse JSON response using jq
Expand Down Expand Up @@ -150,16 +152,20 @@ jobs:
- name: Pack artifacts
id: pack_artifacts
run: |
VFULL=${VFULL:-0.0.1}
echo "VFULL: $VFULL"
ARTIFACT="mor-launch-$TAG_NAME-ubuntu-x64.zip"
echo "Artifact: $ARTIFACT"
LLAMACPP=llama-b3256-bin-ubuntu-x64.zip
MODEL=tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf
wget -nv https://github.com/ggerganov/llama.cpp/releases/download/b3256/$LLAMACPP
wget -nv https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/$MODEL
unzip -o -j $LLAMACPP build/bin/llama-server
echo '{"run":["./llama-server -m ./'$MODEL'","./proxy-router","./morpheus-ui-${VFULL}-x86_64-linux.AppImage"]}' > mor-launch.json
echo '{"run":["./llama-server -m ./'"$MODEL"'","./proxy-router","./morpheus-ui-'"$VFULL"'-x86_64-linux.AppImage"]}' > mor-launch.json
echo "Contents of mor-launch.json: "
cat mor-launch.json
mv ./cli/mor-cli mor-cli
zip -j $ARTIFACT ./LICENSE ./launcher/mor-launch llama-server ./proxy-router/bin/proxy-router .env $MODEL mor-launch.json ./ui-desktop/dist/morpheus-ui-${VFULL}-x86_64-linux.AppImage models-config.json rating-config.json mor-cli
zip -j $ARTIFACT ./LICENSE ./launcher/mor-launch llama-server ./proxy-router/bin/proxy-router .env $MODEL mor-launch.json ./ui-desktop/dist/morpheus-ui-$VFULL-x86_64-linux.AppImage models-config.json rating-config.json mor-cli
- name: Upload artifacts
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -235,6 +241,8 @@ jobs:
wget -nv https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/$MODEL
unzip -o -j $LLAMACPP build/bin/llama-server
echo '{"run":["./llama-server -m ./'$MODEL'","./proxy-router","./MorpheusUI.app/Contents/MacOS/MorpheusUI"]}' > mor-launch.json
echo "Contents of mor-launch.json: "
cat mor-launch.json
mv ./cli/mor-cli mor-cli
unzip ./ui-desktop/dist/morpheus-ui-${VFULL}-x64-mac.zip
zip -j $ARTIFACT ./LICENSE ./launcher/mor-launch ./proxy-router/bin/proxy-router .env llama-server $MODEL mor-launch.json models-config.json rating-config.json mor-cli
Expand Down Expand Up @@ -314,6 +322,8 @@ jobs:
wget -nv https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/$MODEL
unzip -o -j $LLAMACPP build/bin/llama-server
echo '{"run":["./llama-server -m ./'$MODEL'","./proxy-router","./MorpheusUI.app/Contents/MacOS/MorpheusUI"]}' > mor-launch.json
echo "Contents of mor-launch.json: "
cat mor-launch.json
mv ./cli/mor-cli mor-cli
unzip ./ui-desktop/dist/morpheus-ui-${VFULL}-arm64-mac.zip
zip -j $ARTIFACT ./LICENSE ./launcher/mor-launch ./proxy-router/bin/proxy-router .env llama-server $MODEL mor-launch.json models-config.json rating-config.json mor-cli
Expand Down Expand Up @@ -389,21 +399,25 @@ jobs:
- name: Pack artifacts
id: pack_artifacts
run: |
VFULL=${VFULL:-0.0.1}
echo "VFULL: $VFULL"
ARTIFACT="mor-launch-$TAG_NAME-win-x64.zip"
echo "Artifact: $ARTIFACT"
LLAMACPP=llama-b3256-bin-win-avx2-x64.zip
MODEL=tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf
wget -nv https://github.com/ggerganov/llama.cpp/releases/download/b3256/$LLAMACPP
wget -nv https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/$MODEL
unzip -o -j $LLAMACPP llama-server.exe llama.dll ggml.dll
echo '{"run":["./llama-server.exe -m ./'$MODEL'","./proxy-router.exe","./morpheus-ui-${VFULL}-x64-win.exe"]}' > mor-launch.json
echo '{"run":["./llama-server.exe -m ./'"$MODEL"'","./proxy-router.exe","./morpheus-ui-'"$VFULL"'-x64-win.exe"]}' > mor-launch.json
echo "Contents of mor-launch.json: "
cat mor-launch.json
mv .env .env.tmp
sed 's|\./data/|.\\data\\|g' .env.tmp > .env
mv ./proxy-router/bin/proxy-router proxy-router.exe
mv ./cli/mor-cli mor-cli.exe
mv ./launcher/mor-launch mor-launch.exe
mv "./ui-desktop/dist/morpheus-ui-${VFULL}-x64-win" morpheus-ui-${VFULL}-x64-win.exe
7z a $ARTIFACT LICENSE mor-launch.exe proxy-router.exe .env llama-server.exe llama.dll ggml.dll $MODEL mor-launch.json morpheus-ui-${VFULL}-x64-win.exe models-config.json rating-config.json mor-cli.exe
mv "./ui-desktop/dist/morpheus-ui-$VFULL-x64-win" morpheus-ui-$VFULL-x64-win.exe
7z a $ARTIFACT LICENSE mor-launch.exe proxy-router.exe .env llama-server.exe llama.dll ggml.dll $MODEL mor-launch.json morpheus-ui-$VFULL-x64-win.exe models-config.json rating-config.json mor-cli.exe
- name: Upload artifacts
uses: actions/upload-artifact@v4
Expand All @@ -412,7 +426,7 @@ jobs:
name: mor-launch-win-x64.zip

release:
if: ${{ github.repository != 'MorpheusAIs/Morpheus-Lumerin-Node' && (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test' )) || github.event.inputs.create_release == 'true' }}
if: ${{ github.repository != 'MorpheusAIs/Morpheus-Lumerin-Node' && (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test' || github.ref == 'refs/heads/concom' )) || github.event.inputs.create_release == 'true' }}
runs-on: ubuntu-latest
needs:
- Ubuntu-22-x64
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/proxy-router.main.env
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ PROXY_ADDRESS=0.0.0.0:3333
WEB_ADDRESS=0.0.0.0:8082
WEB_PUBLIC_URL=http://localhost:8082
MODELS_CONFIG_PATH=
RATING_CONFIG_PATH=
ETH_NODE_USE_SUBSCRIPTIONS=false
ETH_NODE_ADDRESS=
ETH_NODE_LEGACY_TX=false
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/proxy-router.test.env
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ PROXY_ADDRESS=0.0.0.0:3333
WEB_ADDRESS=0.0.0.0:8082
WEB_PUBLIC_URL=http://localhost:8082
MODELS_CONFIG_PATH=
RATING_CONFIG_PATH=
ETH_NODE_USE_SUBSCRIPTIONS=false
ETH_NODE_ADDRESS=
ETH_NODE_LEGACY_TX=false
Expand Down
76 changes: 76 additions & 0 deletions docs/02a-proxy-router-docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@

# Proxy-Router Docker Setup:

**This document describes setting up the proxy-router component of the Morpheus AI Network in a Docker container ONLY and accessing it via the Swagger API Interface...no GUI or Wallet components are included in this setup**

## Overview:
* The Proxy-Router is a critical component of the Morpheus AI Network. It is responsible for monitoring the blockchain for events and managing the AI models and providers that are available to the network.
* The Proxy-Router is a standalone application that can be run on any server that has access to the blockchain and the AI models.
* This document walks through using Docker to build and run the proxy-router image on your server.

## Pre-Requisites:
* Your AI model has been configured, started and made available to the proxy-router server via a private endpoint (IP:PORT or DNS:PORT) eg: `http://mycoolaimodel.domain.com:8080`
* You have an existing funded wallet with MOR and ETH and also have the `private key` for the wallet (this will be needed for the .env file configuration)
* Your proxy-router must have a **publicly accessible endpoint** for the provider (ip:port or fqdn:port no protocol) eg: `mycoolmornode.domain.com:3333` - this will be used when creating the provider on the blockchain
* Docker and Git are installed and current on your server
* The three key configuration files are located in the same directory as the proxy-router code:
* .env
* models-config.json
* rating-config.json

## Installation & Configuration Steps:
1. Clone the source code from the repository:
* `git clone -b main https://github.com/Lumerin-protocol/Morpheus-Lumerin-Node.git`
1. Change to the proxy-router directory:
* `cd Morpheus-Lumerin-Node\proxy-router`
1. Configure the 3 key files for your environment:
1. Environment file configuration
1. Copy the example file to .env:
* Linux/Mac: `cp .env.example .env`
* Windows: `copy .env.example.win .env`
1. Edit values within the .env as desired
* Add your private key to`WALLET_PRIVATE_KEY=`
* Modify the following values to ensure that those files remain "outside of the running container" for persistence and are mounted by the docker-compose.yml file's `volume` directive
* `MODELS_CONFIG_PATH=/app/data/models-config.json`
* `RATING_CONFIG_PATH=/app/data/rating-config.json`
* `PROXY_STORAGE_PATH=/app/data/`
1. Choose the **blockchain** you'd like to work on...**Arbitrum MAINNET is the default**
* To operate on the Sepolia Arbitrum TESTNET,
* Uncomment the `TESTNET VALUES` and comment the `MAINNET VALUES` lines & save the file
1. Models Configuration file
1. Copy the example file to models-config.json:
* Linux/Mac: `cp models-config.json.example models-config.json`
* Windows: `copy models-config.json.example models-config.json`
1. Edit the models-config.json file to include the models you'd like to use.
1. Details here: [models-config.json.md](models-config.json.md)
1. Once your provider is up and running, deploy a new model and model bid via the API interface (you will need to update the `modelId` for the configuration)
1. Rating Configuration file
1. Copy the example file to rating-config.json:
* Linux/Mac: `cp rating-config.json.example rating-config.json`
* Windows: `copy rating-config.json.example rating-config.json`
1. Edit the rating-config.json file to include the weights and preferred providers you'd like to use.
1. Details here: [rating-config.json.md](rating-config.json.md)

## Build the proxy-router Docker Image:
1. Build the Docker image using the provided `docker_build.sh` script
* `./docker_build.sh --build`
* This script pulls the current Git tag and version, builds the docker image with all the port and defaults defined in the docker-compose.yml file

## Running the proxy-router Docker Container:
1. Run the Docker container using the provided `docker_build.sh` script
* `./docker_build.sh --run`
* This script runs the docker container with the port and volume mappings defined in the docker-compose.yml file
* The proxy-router will start and begin listening for blockchain events

## Validating Steps:
1. Once the proxy-router is running, you can navigate to the Swagger API Interface (http://localhost:8082/swagger/index.html as example) to validate that the proxy-router is running and listening for blockchain events
1. Once validated, you can move on and create your provider, model and bid on the blockchain [03-provider-offer.md](03-provider-offer.md)

## NOTES:
* We have created docker-compose.yml, Dockerfile and docker_build.sh scripts to ease configuration and deployment of the proxy-router in a containerized environment
* Use these files as guides for applying to your system needs and configurations, private key, eth_node, ports, endpoints, volumes, .env, models-config.json and rating-config.json will need to be adjusted to your specific needs
* In most cases, the default .env file will work for the proxy-router...In some cases you will want to modify the .env file with advanced capability (log entries, private keys, private endpoints, etc)
* Please see the following for more information on these key config files:
* [proxy-router.all.env](proxy-router.all.env)
* [models-config.json.md](models-config.json.md)
* [rating-config.json.md](rating-config.json.md)
1 change: 1 addition & 0 deletions proxy-router/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ PROXY_ADDRESS=0.0.0.0:3333
WEB_ADDRESS=0.0.0.0:8082
WEB_PUBLIC_URL=http://localhost:8082
MODELS_CONFIG_PATH=
RATING_CONFIG_PATH=
ETH_NODE_USE_SUBSCRIPTIONS=false
ETH_NODE_ADDRESS=
ETH_NODE_LEGACY_TX=false
Expand Down
1 change: 1 addition & 0 deletions proxy-router/.env.example.win
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ PROXY_ADDRESS=0.0.0.0:3333
WEB_ADDRESS=0.0.0.0:8082
WEB_PUBLIC_URL=http://localhost:8082
MODELS_CONFIG_PATH=
RATING_CONFIG_PATH=
ETH_NODE_USE_SUBSCRIPTIONS=false
ETH_NODE_ADDRESS=
ETH_NODE_LEGACY_TX=false
Expand Down
12 changes: 11 additions & 1 deletion proxy-router/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,14 @@ bin

data*

models-config.json
models-config.json
rating-config.json

#Badger DB
*.vlog
*.mem
DISCARD
KEYREGISTRY
LOCK
MANIFEST
chats/
15 changes: 5 additions & 10 deletions proxy-router/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Stage 1: Build
FROM golang:1.22.3-alpine as builder
FROM golang:1.22.3-alpine AS builder

# Capture the Git tag and commit hash during build
ARG TAG_NAME
Expand All @@ -10,16 +10,11 @@ ENV COMMIT=$COMMIT
WORKDIR /app
COPY . .

# Build the Go binary (recommended for linux/amd64...for MacARM use buildx)
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
# Build the Go binary (Docker will build automatically to the OS and Arch that is hosting)
RUN CGO_ENABLED=0 \
TAG_NAME=$TAG_NAME COMMIT=$COMMIT ./build.sh && \
cp /bin/sh /app/sh && chmod +x /app/sh

# Multiplatform Build Notes:
# to support both amd64 and arm64, use Docker’s Buildx to create a multi-architecture image
# docker buildx create --use
# docker buildx build --platform linux/amd64,linux/arm64 -t proxy-router:latest .

# Stage 2: Final Image
FROM scratch
WORKDIR /app
Expand All @@ -29,8 +24,8 @@ COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/bin/proxy-router /usr/bin/

# Optional Copy utilities from busybox image
# COPY --from=busybox /bin /bin
# COPY --from=busybox /lib /lib
COPY --from=busybox /bin /bin
COPY --from=busybox /lib /lib

SHELL ["/bin/sh", "-c"]
EXPOSE 3333 8082
Expand Down
30 changes: 14 additions & 16 deletions proxy-router/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ func start() error {
docs.SwaggerInfo.Host = hostWithoutProtocol
} else if cfg.Web.Address != "" {
docs.SwaggerInfo.Host = cfg.Web.Address
} else {
docs.SwaggerInfo.Host = "localhost:8082"
}
docs.SwaggerInfo.Version = config.BuildVersion

docs.SwaggerInfo.Version = config.BuildVersion

log, err := lib.NewLogger(cfg.Log.LevelApp, cfg.Log.Color, cfg.Log.IsProd, cfg.Log.JSON, mainLogFilePath)
if err != nil {
return err
Expand Down Expand Up @@ -227,11 +227,6 @@ func start() error {
}
appLog.Infof("connected to ethereum node: %s, chainID: %d", cfg.Blockchain.EthNodeAddress, chainID)

publicUrl, err := url.Parse(cfg.Web.PublicUrl)
if err != nil {
return err
}

storage := storages.NewStorage(badgerLog, cfg.Proxy.StoragePath)
sessionStorage := storages.NewSessionStorage(storage)

Expand All @@ -246,19 +241,13 @@ func start() error {

var logWatcher contracts.LogWatcher
if cfg.Blockchain.UseSubscriptions {
logWatcher = contracts.NewLogWatcherSubscription(ethClient, cfg.Blockchain.MaxReconnects, log)
logWatcher = contracts.NewLogWatcherSubscription(ethClient, cfg.Blockchain.MaxReconnects, rpcLog)
appLog.Infof("using websocket log subscription for blockchain events")
} else {
logWatcher = contracts.NewLogWatcherPolling(ethClient, cfg.Blockchain.PollingInterval, cfg.Blockchain.MaxReconnects, log)
logWatcher = contracts.NewLogWatcherPolling(ethClient, cfg.Blockchain.PollingInterval, cfg.Blockchain.MaxReconnects, rpcLog)
appLog.Infof("using polling for blockchain events")
}

modelConfigLoader := config.NewModelConfigLoader(cfg.Proxy.ModelsConfigPath, log)
err = modelConfigLoader.Init()
if err != nil {
log.Warnf("failed to load model config: %s, run with empty", err)
}

scorer, err := config.LoadRating(cfg.Proxy.RatingConfigPath, log)
if err != nil {
return err
Expand All @@ -271,10 +260,17 @@ func start() error {
sessionRouter := registries.NewSessionRouter(*cfg.Marketplace.DiamondContractAddress, ethClient, multicallBackend, log)
marketplace := registries.NewMarketplace(*cfg.Marketplace.DiamondContractAddress, ethClient, multicallBackend, log)
sessionRepo := sessionrepo.NewSessionRepositoryCached(sessionStorage, sessionRouter, marketplace)
proxyRouterApi := proxyapi.NewProxySender(chainID, publicUrl, wallet, contractLogStorage, sessionStorage, sessionRepo, log)
proxyRouterApi := proxyapi.NewProxySender(chainID, wallet, contractLogStorage, sessionStorage, sessionRepo, log)
explorer := blockchainapi.NewExplorerClient(cfg.Blockchain.ExplorerApiUrl, *cfg.Marketplace.MorTokenAddress, cfg.Blockchain.ExplorerRetryDelay, cfg.Blockchain.ExplorerMaxRetries)
blockchainApi := blockchainapi.NewBlockchainService(ethClient, multicallBackend, *cfg.Marketplace.DiamondContractAddress, *cfg.Marketplace.MorTokenAddress, explorer, wallet, proxyRouterApi, sessionRepo, scorer, proxyLog, cfg.Blockchain.EthLegacyTx)
proxyRouterApi.SetSessionService(blockchainApi)

modelConfigLoader := config.NewModelConfigLoader(cfg.Proxy.ModelsConfigPath, valid, blockchainApi, &aiengine.ConnectionChecker{}, log)
err = modelConfigLoader.Init()
if err != nil {
log.Warnf("failed to load model config, running with empty: %s", err)
}

aiEngine := aiengine.NewAiEngine(proxyRouterApi, chatStorage, modelConfigLoader, log)

eventListener := blockchainapi.NewEventsListener(sessionRepo, sessionRouter, wallet, logWatcher, log)
Expand All @@ -299,6 +295,8 @@ func start() error {
cancel()
}()

log.Infof("API docs available at %s/swagger/index.html", cfg.Web.PublicUrl)

proxy := proxyctl.NewProxyCtl(eventListener, wallet, chainID, log, connLog, cfg.Proxy.Address, schedulerLogFactory, sessionStorage, modelConfigLoader, valid, aiEngine, blockchainApi, sessionRepo, sessionExpiryHandler)
err = proxy.Run(ctx)

Expand Down
13 changes: 10 additions & 3 deletions proxy-router/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
services:
proxy-router:
build: .
build:
context: .
args:
COMMIT: ${COMMIT:-unknown}
TAG_NAME: ${TAG_NAME:-latest}
image: proxy-router:${TAG_NAME}
env_file:
- .env
ports:
- 8082:8082
- 3333:3333
- "8082:8082"
- "3333:3333"
volumes:
- .:/app/data
Loading

0 comments on commit 55ecaa8

Please sign in to comment.