-
-
Notifications
You must be signed in to change notification settings - Fork 364
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 2817271
Showing
52 changed files
with
7,466 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
.DS_Store | ||
node_modules | ||
/build | ||
/.svelte-kit | ||
/package | ||
.env | ||
.env.* | ||
!.env.example | ||
|
||
# Ignore files for PNPM, NPM and YARN | ||
pnpm-lock.yaml | ||
package-lock.json | ||
yarn.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/** @type { import("eslint").Linter.Config } */ | ||
module.exports = { | ||
root: true, | ||
extends: [ | ||
'eslint:recommended', | ||
'plugin:@typescript-eslint/recommended', | ||
'plugin:svelte/recommended', | ||
'prettier' | ||
], | ||
parser: '@typescript-eslint/parser', | ||
plugins: ['@typescript-eslint'], | ||
parserOptions: { | ||
sourceType: 'module', | ||
ecmaVersion: 2020, | ||
extraFileExtensions: ['.svelte'] | ||
}, | ||
env: { | ||
browser: true, | ||
es2017: true, | ||
node: true | ||
}, | ||
overrides: [ | ||
{ | ||
files: ['*.svelte'], | ||
parser: 'svelte-eslint-parser', | ||
parserOptions: { | ||
parser: '@typescript-eslint/parser' | ||
} | ||
} | ||
] | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
.DS_Store | ||
node_modules | ||
/build | ||
/.svelte-kit | ||
/package | ||
.env | ||
.env.* | ||
!.env.example | ||
vite.config.js.timestamp-* | ||
vite.config.ts.timestamp-* | ||
backend/tmp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
engine-strict=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Ignore files for PNPM, NPM and YARN | ||
pnpm-lock.yaml | ||
package-lock.json | ||
yarn.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"useTabs": true, | ||
"singleQuote": true, | ||
"trailingComma": "none", | ||
"printWidth": 100, | ||
"plugins": ["prettier-plugin-svelte"], | ||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
FROM node:20-alpine3.19 AS builder | ||
WORKDIR /app | ||
COPY package*.json . | ||
RUN npm ci | ||
COPY . . | ||
RUN npm run build | ||
RUN npm prune --production | ||
|
||
FROM node:20-alpine3.19 | ||
WORKDIR /app | ||
COPY --from=builder /app/build build/ | ||
COPY --from=builder /app/node_modules node_modules/ | ||
COPY package.json . | ||
EXPOSE 3000 | ||
ENV NODE_ENV=production | ||
CMD [ "node", "build" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
FROM node:20-alpine3.19 | ||
WORKDIR /app | ||
EXPOSE 5173 | ||
|
||
CMD ["sh", "-c", "npm install && npm run dev -- --host"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
PHONY: build-dev | ||
build-dev: | ||
docker-compose -f ./docker-compose.dev.yaml build | ||
|
||
PHONY: dev | ||
dev: build-dev | ||
docker-compose -f ./docker-compose.dev.yaml up | ||
|
||
PHONY: run | ||
run: build-dev | ||
docker-compose -f ./docker-compose.dev.yaml up -d | ||
|
||
PHONY: stop | ||
stop: | ||
docker-compose -f ./docker-compose.dev.yaml down | ||
|
||
PHONY: update | ||
update: | ||
git pull | ||
|
||
PHONY: upgrade | ||
upgrade: stop update build-dev run |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# LLM search engine | ||
|
||
## Status | ||
|
||
This is a proof of concept, the code is horrible. I didn't intend to make this public yet, but I wanted to share it with a few people. | ||
Please open issues and PRs if you have any suggestions. | ||
|
||
## How it works | ||
|
||
1. The user query is sent to server | ||
2. The server starts an agent chain | ||
3. The agent (in our case `starling-lm` running on Ollama) will process the query and select one of its tools | ||
- Websearch (using SearXNG) will scrape the top `n` results from the web (the agent will choose the search query). Remove all unnecessary information (like html tags) and store the result into a vector db | ||
- SearchVectorDB will search the vector db for the most similar results to the query | ||
4. Step 3 will happen multiple times, with the agent choosing different tools and combining the results | ||
5. The final result is sent back to the user and displayed in the frontend | ||
|
||
While this is happening, the user can see the progress of the agents steps in the frontend. | ||
|
||
## Running / Development | ||
|
||
### Requirements | ||
|
||
- A running [Ollama](https://ollama.com/) server somewhere in your network | ||
- a model named `search:latest` | ||
- (I recommend `hermes-2-pro-mistral` or `starling-lm-7b-beta`) | ||
- `all-minilm` for embeddings | ||
- Docker Compose | ||
|
||
Included in the compose file are | ||
- search backend (based on the Go Langchain library) | ||
- search frontend (svelte & tailwind) | ||
- Chroma DB (for storing search results in vector space) | ||
- SearXNG (meta search engine used by the agent chain) | ||
- Redis (for caching search results) | ||
|
||
``` | ||
git clone https://github.com/nilsherzig/LocalSearchUI.git | ||
# make sure to check the env vars inside the compose file | ||
# build the containers and start the services | ||
make dev | ||
``` | ||
|
||
## Roadmap | ||
|
||
### backend | ||
|
||
- Automatic LLM download to Ollama if not present | ||
- Forced backlinks in final answer | ||
- I have no idea how to do this, besides asking the LLM haha | ||
- Force the search LLM to respond in JSON with links? | ||
- Another round of formatting LLM after this to include these links into the final text? | ||
- Persistent user accounts | ||
- add your own files | ||
- select splitter values based on complexity of the question | ||
- broad vs narrow | ||
|
||
### interface | ||
|
||
- CLI version | ||
- "tree view" for actions | ||
- different LLM backends (like OpenAI or Anthropic) | ||
- settings table for different models | ||
- Ollama model select dropdown | ||
- would require a lot of other values to be exposed to the UI | ||
- render latex |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
root = "." | ||
testdata_dir = "testdata" | ||
tmp_dir = "tmp" | ||
|
||
[build] | ||
args_bin = [] | ||
bin = "./tmp/main" | ||
cmd = "go build -o ./tmp/main ." | ||
delay = 1000 | ||
exclude_dir = ["assets", "tmp", "vendor", "testdata"] | ||
exclude_file = [] | ||
exclude_regex = ["_test.go"] | ||
exclude_unchanged = false | ||
follow_symlink = false | ||
full_bin = "" | ||
include_dir = [] | ||
include_ext = ["go", "tpl", "tmpl", "html"] | ||
include_file = [] | ||
kill_delay = "0s" | ||
log = "build-errors.log" | ||
poll = false | ||
poll_interval = 0 | ||
post_cmd = [] | ||
pre_cmd = [] | ||
rerun = false | ||
rerun_delay = 500 | ||
send_interrupt = false | ||
stop_on_error = true | ||
|
||
[color] | ||
app = "" | ||
build = "yellow" | ||
main = "magenta" | ||
runner = "green" | ||
watcher = "cyan" | ||
|
||
[log] | ||
main_only = false | ||
time = false | ||
|
||
[misc] | ||
clean_on_exit = false | ||
|
||
[screen] | ||
clear_on_rebuild = false | ||
keep_scroll = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Stage 1: Build | ||
FROM golang:1.21.7 AS builder | ||
|
||
# Set the Current Working Directory inside the container | ||
WORKDIR /app | ||
|
||
# Copy go mod and sum files | ||
COPY go.mod go.sum ./ | ||
|
||
# Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed | ||
RUN go mod download | ||
|
||
# Copy the source from the current directory to the Working Directory inside the container | ||
COPY . . | ||
|
||
# Build the Go app | ||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main . | ||
|
||
# Stage 2: Run | ||
FROM alpine:latest | ||
|
||
RUN apk --no-cache add ca-certificates | ||
|
||
WORKDIR /root/ | ||
|
||
# Copy the Pre-built binary file from the previous stage | ||
COPY --from=builder /app/main . | ||
|
||
# Expose port 8080 to the outside world | ||
EXPOSE 8080 | ||
|
||
# Command to run the executable | ||
CMD ["./main"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
FROM golang:alpine3.19 | ||
|
||
WORKDIR /app | ||
RUN go install github.com/cosmtrek/air@latest | ||
EXPOSE 8080 | ||
|
||
CMD ["air"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
"log/slog" | ||
"time" | ||
|
||
"github.com/nilsherzig/localLLMSearch/llm_tools" | ||
"github.com/nilsherzig/localLLMSearch/utils" | ||
"github.com/tmc/langchaingo/agents" | ||
"github.com/tmc/langchaingo/chains" | ||
"github.com/tmc/langchaingo/llms" | ||
"github.com/tmc/langchaingo/tools" | ||
) | ||
|
||
func startAgentChain(ctx context.Context, outputChan chan<- utils.HttpJsonStreamElement, userQuery utils.ClientQuery) error { | ||
defer func() { | ||
// send a close message to the client when the function ends | ||
// the client can use this to close the connection gracefully | ||
// outputChan <- utils.HttpJsonStreamElement{ | ||
// Close: true, | ||
// } | ||
|
||
// this defer acts as a try catch block around the current function | ||
// this prevents the whole server from crashing when an error occurs | ||
|
||
// TODO: figure out how to stop the "sending on closed channel" error | ||
// when the client disconnects | ||
if r := recover(); r != nil { | ||
log.Printf("Recovered from panic: %v", r) | ||
} | ||
}() | ||
|
||
// used to set the vector db namespace | ||
startTime := time.Now() | ||
session := utils.GetSessionString() | ||
slog.Info("Starting agent chain", "session", session, "userQuery", userQuery, "startTime", startTime) | ||
|
||
// llm, err := utils.NewGPT35() | ||
// llm, err := utils.NewGPT4() | ||
llm, err := utils.NewOllama() | ||
// llm, err := | ||
if err != nil { | ||
log.Printf("Error creating new LLM: %v", err) | ||
return err | ||
} | ||
|
||
agentTools := []tools.Tool{ | ||
tools.Calculator{}, | ||
llm_tools.WebSearch{ | ||
CallbacksHandler: utils.CustomHandler{ | ||
OutputChan: outputChan, | ||
}, | ||
SessionString: session, | ||
}, | ||
llm_tools.SearchVectorDB{ | ||
CallbacksHandler: utils.CustomHandler{ | ||
OutputChan: outputChan, | ||
}, | ||
SessionString: session, | ||
}, | ||
// llm_tools.Feedback{ | ||
// CallbacksHandler: utils.CustomHandler{}, | ||
// Query: userQuery, | ||
// Llm: llm, | ||
// }, | ||
} | ||
|
||
executor, err := agents.Initialize( | ||
llm, | ||
agentTools, | ||
agents.ZeroShotReactDescription, | ||
agents.WithParserErrorHandler(agents.NewParserErrorHandler(func(s string) string { | ||
outputChan <- utils.HttpJsonStreamElement{ | ||
Message: fmt.Sprintf("Parsing Error. %s", s), | ||
Stream: false, | ||
} | ||
return utils.ParsingErrorPrompt() | ||
})), | ||
|
||
agents.WithMaxIterations(userQuery.MaxIterations), | ||
agents.WithCallbacksHandler(utils.CustomHandler{ | ||
OutputChan: outputChan, | ||
}), | ||
) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
temp := 0.0 | ||
|
||
finalAnswer, err := chains.Run(ctx, executor, userQuery.Prompt, chains.WithTemperature(temp)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
newAns, err := llm.Call(ctx, utils.FormatTextAsMArkdownPrompt(finalAnswer), | ||
llms.WithTemperature(temp), | ||
llms.WithStreamingFunc(func(ctx context.Context, chunk []byte) error { | ||
outputChan <- utils.HttpJsonStreamElement{ | ||
StepType: utils.StepHandleFinalAnswer, | ||
Message: string(chunk), | ||
Stream: true, | ||
} | ||
return nil | ||
}), | ||
) | ||
if err != nil { | ||
return err | ||
} | ||
_ = newAns | ||
slog.Info("finished chain", "session", session, "duration", time.Since(startTime), "finalAnswer", newAns) | ||
|
||
return nil | ||
} |
Oops, something went wrong.