Compare commits

..

1 Commits

Author SHA1 Message Date
Richard Palethorpe
9434524e51 fix(ui): Don't try to pass unserializable Go objects to status UI
Signed-off-by: Richard Palethorpe <io@richiejp.com>
2025-04-13 14:50:31 +01:00
8 changed files with 93 additions and 128 deletions

View File

@@ -49,10 +49,10 @@ cd LocalAGI
docker compose up
# NVIDIA GPU setup
docker compose -f docker-compose.nvidia.yaml up
docker compose --profile nvidia up
# Intel GPU setup (for Intel Arc and integrated GPUs)
docker compose -f docker-compose.intel.yaml up
docker compose --profile intel up
# Start with a specific model (see available models in models.localai.io, or localai.io to use any model in huggingface)
MODEL_NAME=gemma-3-12b-it docker compose up
@@ -61,40 +61,11 @@ MODEL_NAME=gemma-3-12b-it docker compose up
MODEL_NAME=gemma-3-12b-it \
MULTIMODAL_MODEL=minicpm-v-2_6 \
IMAGE_MODEL=flux.1-dev \
docker compose -f docker-compose.nvidia.yaml up
docker compose --profile nvidia up
```
Now you can access and manage your agents at [http://localhost:8080](http://localhost:8080)
## 📚🆕 Local Stack Family
🆕 LocalAI is now part of a comprehensive suite of AI tools designed to work together:
<table>
<tr>
<td width="50%" valign="top">
<a href="https://github.com/mudler/LocalAI">
<img src="https://raw.githubusercontent.com/mudler/LocalAI/refs/heads/rebranding/core/http/static/logo_horizontal.png" width="300" alt="LocalAI Logo">
</a>
</td>
<td width="50%" valign="top">
<h3><a href="https://github.com/mudler/LocalRecall">LocalAI</a></h3>
<p>LocalAI is the free, Open Source OpenAI alternative. LocalAI act as a drop-in replacement REST API that's compatible with OpenAI API specifications for local AI inferencing. Does not require GPU.</p>
</td>
</tr>
<tr>
<td width="50%" valign="top">
<a href="https://github.com/mudler/LocalRecall">
<img src="https://raw.githubusercontent.com/mudler/LocalRecall/refs/heads/main/static/localrecall_horizontal.png" width="300" alt="LocalRecall Logo">
</a>
</td>
<td width="50%" valign="top">
<h3><a href="https://github.com/mudler/LocalRecall">LocalRecall</a></h3>
<p>A REST-ful API and knowledge base management system that provides persistent memory and storage capabilities for AI agents.</p>
</td>
</tr>
</table>
## 🖥️ Hardware Configurations
LocalAGI supports multiple hardware configurations through Docker Compose profiles:
@@ -110,7 +81,7 @@ LocalAGI supports multiple hardware configurations through Docker Compose profil
- Uses CUDA for acceleration
- Best for high-performance inference
- Supports text, multimodal, and image generation models
- Run with: `docker compose -f docker-compose.nvidia.yaml up`
- Run with: `docker compose --profile nvidia up`
- Default models:
- Text: `arcee-agent`
- Multimodal: `minicpm-v-2_6`
@@ -126,7 +97,7 @@ LocalAGI supports multiple hardware configurations through Docker Compose profil
- Uses SYCL for acceleration
- Best for Intel-based systems
- Supports text, multimodal, and image generation models
- Run with: `docker compose -f docker-compose.intel.yaml up`
- Run with: `docker compose --profile intel up`
- Default models:
- Text: `arcee-agent`
- Multimodal: `minicpm-v-2_6`
@@ -149,13 +120,13 @@ MODEL_NAME=gemma-3-12b-it docker compose up
MODEL_NAME=gemma-3-12b-it \
MULTIMODAL_MODEL=minicpm-v-2_6 \
IMAGE_MODEL=flux.1-dev \
docker compose -f docker-compose.nvidia.yaml up
docker compose --profile nvidia up
# Intel GPU with custom models
MODEL_NAME=gemma-3-12b-it \
MULTIMODAL_MODEL=minicpm-v-2_6 \
IMAGE_MODEL=sd-1.5-ggml \
docker compose -f docker-compose.intel.yaml up
docker compose --profile intel up
```
If no models are specified, it will use the defaults:

View File

@@ -260,7 +260,6 @@ var _ = Describe("Agent test", func() {
WithLLMAPIURL(apiURL),
WithModel(testModel),
WithLLMAPIKey(apiKeyURL),
WithTimeout("10m"),
WithNewConversationSubscriber(func(m openai.ChatCompletionMessage) {
mu.Lock()
message = m

View File

@@ -1,33 +0,0 @@
services:
localai:
extends:
file: docker-compose.yaml
service: localai
environment:
- LOCALAI_SINGLE_ACTIVE_BACKEND=true
- DEBUG=true
image: localai/localai:master-sycl-f32-ffmpeg-core
devices:
# On a system with integrated GPU and an Arc 770, this is the Arc 770
- /dev/dri/card1
- /dev/dri/renderD129
command:
- ${MODEL_NAME:-arcee-agent}
- ${MULTIMODAL_MODEL:-minicpm-v-2_6}
- ${IMAGE_MODEL:-sd-1.5-ggml}
- granite-embedding-107m-multilingual
localrecall:
extends:
file: docker-compose.yaml
service: localrecall
localrecall-healthcheck:
extends:
file: docker-compose.yaml
service: localrecall-healthcheck
localagi:
extends:
file: docker-compose.yaml
service: localagi

View File

@@ -1,31 +0,0 @@
services:
localai:
extends:
file: docker-compose.yaml
service: localai
environment:
- LOCALAI_SINGLE_ACTIVE_BACKEND=true
- DEBUG=true
image: localai/localai:master-sycl-f32-ffmpeg-core
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
localrecall:
extends:
file: docker-compose.yaml
service: localrecall
localrecall-healthcheck:
extends:
file: docker-compose.yaml
service: localrecall-healthcheck
localagi:
extends:
file: docker-compose.yaml
service: localagi

View File

@@ -7,9 +7,8 @@ services:
# Image list (dockerhub): https://hub.docker.com/r/localai/localai
image: localai/localai:master-ffmpeg-core
command:
# - gemma-3-12b-it
- ${MODEL_NAME:-arcee-agent}
- ${MULTIMODAL_MODEL:-minicpm-v-2_6}
- ${IMAGE_MODEL:-flux.1-dev}
- granite-embedding-107m-multilingual
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/readyz"]
@@ -25,6 +24,44 @@ services:
- ./volumes/models:/build/models:cached
- ./volumes/images:/tmp/generated/images
localai-nvidia:
profiles: ["nvidia"]
extends:
service: localai
environment:
- LOCALAI_SINGLE_ACTIVE_BACKEND=true
- DEBUG=true
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
command:
- ${MODEL_NAME:-arcee-agent}
- ${MULTIMODAL_MODEL:-minicpm-v-2_6}
- ${IMAGE_MODEL:-flux.1-dev}
- granite-embedding-107m-multilingual
localai-intel:
profiles: ["intel"]
environment:
- LOCALAI_SINGLE_ACTIVE_BACKEND=true
- DEBUG=true
extends:
service: localai
image: localai/localai:master-sycl-f32-ffmpeg-core
devices:
# On a system with integrated GPU and an Arc 770, this is the Arc 770
- /dev/dri/card1
- /dev/dri/renderD129
command:
- ${MODEL_NAME:-arcee-agent}
- ${MULTIMODAL_MODEL:-minicpm-v-2_6}
- ${IMAGE_MODEL:-sd-1.5-ggml}
- granite-embedding-107m-multilingual
localrecall:
image: quay.io/mudler/localrecall:main
ports:
@@ -60,8 +97,6 @@ services:
#image: quay.io/mudler/localagi:master
environment:
- LOCALAGI_MODEL=${MODEL_NAME:-arcee-agent}
- LOCALAGI_MULTIMODAL_MODEL=${MULTIMODAL_MODEL:-minicpm-v-2_6}
- LOCALAGI_IMAGE_MODEL=${IMAGE_MODEL:-sd-1.5-ggml}
- LOCALAGI_LLM_API_URL=http://localai:8080
#- LOCALAGI_LLM_API_KEY=sk-1234567890
- LOCALAGI_LOCALRAG_URL=http://localrecall:8080
@@ -71,4 +106,32 @@ services:
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ./volumes/localagi/:/pool
- ./volumes/localagi/:/pool
localagi-nvidia:
profiles: ["nvidia"]
extends:
service: localagi
environment:
- LOCALAGI_MODEL=${MODEL_NAME:-arcee-agent}
- LOCALAGI_MULTIMODAL_MODEL=${MULTIMODAL_MODEL:-minicpm-v-2_6}
- LOCALAGI_IMAGE_MODEL=${IMAGE_MODEL:-flux.1-dev}
- LOCALAGI_LLM_API_URL=http://localai:8080
- LOCALAGI_LOCALRAG_URL=http://localrecall:8080
- LOCALAGI_STATE_DIR=/pool
- LOCALAGI_TIMEOUT=5m
- LOCALAGI_ENABLE_CONVERSATIONS_LOGGING=false
localagi-intel:
profiles: ["intel"]
extends:
service: localagi
environment:
- LOCALAGI_MODEL=${MODEL_NAME:-arcee-agent}
- LOCALAGI_MULTIMODAL_MODEL=${MULTIMODAL_MODEL:-minicpm-v-2_6}
- LOCALAGI_IMAGE_MODEL=${IMAGE_MODEL:-sd-1.5-ggml}
- LOCALAGI_LLM_API_URL=http://localai:8080
- LOCALAGI_LOCALRAG_URL=http://localrecall:8080
- LOCALAGI_STATE_DIR=/pool
- LOCALAGI_TIMEOUT=5m
- LOCALAGI_ENABLE_CONVERSATIONS_LOGGING=false

View File

@@ -1,13 +1,12 @@
import { useState, useEffect } from 'react';
import { useParams, Link, useNavigate } from 'react-router-dom';
import { useParams, Link } from 'react-router-dom';
function AgentStatus() {
const { name } = useParams();
const navigate = useNavigate();
const [statusData, setStatusData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [eventSource, setEventSource] = useState(null);
const [_eventSource, setEventSource] = useState(null);
const [liveUpdates, setLiveUpdates] = useState([]);
// Update document title
@@ -49,7 +48,7 @@ function AgentStatus() {
const data = JSON.parse(event.data);
setLiveUpdates(prev => [data, ...prev.slice(0, 19)]); // Keep last 20 updates
} catch (err) {
console.error('Error parsing SSE data:', err);
setLiveUpdates(prev => [event.data, ...prev.slice(0, 19)]);
}
});
@@ -129,23 +128,9 @@ function AgentStatus() {
<h2 className="text-sm font-semibold mb-2">Agent Action:</h2>
<div className="status-details">
<div className="status-row">
<span className="status-label">Result:</span>
<span className="status-value">{formatValue(item.Result)}</span>
<span className="status-label">{index}</span>
<span className="status-value">{formatValue(item)}</span>
</div>
<div className="status-row">
<span className="status-label">Action:</span>
<span className="status-value">{formatValue(item.Action)}</span>
</div>
<div className="status-row">
<span className="status-label">Parameters:</span>
<span className="status-value pre-wrap">{formatValue(item.Params)}</span>
</div>
{item.Reasoning && (
<div className="status-row">
<span className="status-label">Reasoning:</span>
<span className="status-value reasoning">{formatValue(item.Reasoning)}</span>
</div>
)}
</div>
</div>
</div>

View File

@@ -30,7 +30,6 @@ export default defineConfig(({ mode }) => {
'/status': backendUrl,
'/action': backendUrl,
'/actions': backendUrl,
'/avatars': backendUrl
}
}
}

View File

@@ -4,6 +4,7 @@ import (
"crypto/subtle"
"embed"
"errors"
"fmt"
"math/rand"
"net/http"
"path/filepath"
@@ -238,9 +239,20 @@ func (app *App) registerRoutes(pool *state.AgentPool, webapp *fiber.App) {
history = &state.Status{ActionResults: []types.ActionState{}}
}
entries := []string{}
for _, h := range Reverse(history.Results()) {
entries = append(entries, fmt.Sprintf(
"Result: %v Action: %v Params: %v Reasoning: %v",
h.Result,
h.Action.Definition().Name,
h.Params,
h.Reasoning,
))
}
return c.JSON(fiber.Map{
"Name": c.Params("name"),
"History": Reverse(history.Results()),
"History": entries,
})
})