how to build local knowledge base by LLM 1?
Table of Contents
we can build a local knowledge base powered by RAG (Retrieval-Augmented Generation) using:
- 🔍 ChromaDB (embedded vector DB)
- 🧠 Ollama (local LLM: Mistral, LLaMA, etc.)
- ✍️ Go code to ingest documents, embed chunks, and query with context
✅ Prerequisites
Install the following tools:
# Chroma as a Python backend server
pip install chromadb
# Ollama for running local LLMs (like mistral)
brew install ollama # or follow: https://ollama.com/download
ollama run mistral # or other models
# Go packages
go get github.com/go-resty/resty/v2
go get github.com/google/uuid
🗂️ Project Structure
go-local-rag/
├── main.go
├── embedder.go # Calls embedding model (local or OpenAI)
├── chroma_client.go # Handles Chroma DB operations
├── prompt.go # Constructs LLM prompts
├── docs/
│ └── sample.txt
🧠 Step-by-Step Sample: main.go
package main
import (
"fmt"
"log"
"strings"
"your_project/chroma"
"your_project/embedder"
"your_project/prompt"
)
func main() {
docs := []string{
"Go is a statically typed, compiled programming language designed at Google.",
"It is syntactically similar to C, but with memory safety, garbage collection, and CSP-style concurrency.",
}
// Step 1: Embed and store in ChromaDB
for _, doc := range docs {
chunks := strings.Split(doc, ". ") // naive splitter
for _, chunk := range chunks {
vec := embedder.EmbedText(chunk)
chroma.Upsert("golang-knowledge", chunk, vec)
}
}
// Step 2: User query
query := "What is Go and who designed it?"
qvec := embedder.EmbedText(query)
// Step 3: Retrieve relevant docs
topChunks := chroma.Query("golang-knowledge", qvec)
// Step 4: Compose prompt and send to LLM (Ollama)
finalPrompt := prompt.Build(query, topChunks)
resp := prompt.CallOllama("mistral", finalPrompt)
fmt.Println("🔎 Answer:\n", resp)
}
🔌 Sample: embedder.go
(Ollama embedding or OpenAI)
package embedder
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func EmbedText(text string) []float64 {
payload := map[string]string{"model": "nomic-embed-text", "prompt": text}
body, _ := json.Marshal(payload)
resp, err := http.Post("http://localhost:11434/api/embeddings", "application/json", bytes.NewBuffer(body))
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
var result struct {
Embedding []float64 `json:"embedding"`
}
json.NewDecoder(resp.Body).Decode(&result)
return result.Embedding
}
🧱 Sample: chroma_client.go
package chroma
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/google/uuid"
)
type ChromaDoc struct {
ID string
Content string
Vector []float64
}
var chromaURL = "http://localhost:8000"
func Upsert(collection string, content string, vec []float64) {
payload := map[string]interface{}{
"ids": []string{uuid.New().String()},
"documents": []string{content},
"embeddings": [][]float64{vec},
}
data, _ := json.Marshal(payload)
url := fmt.Sprintf("%s/api/v1/collections/%s/upsert", chromaURL, collection)
_, err := http.Post(url, "application/json", bytes.NewReader(data))
if err != nil {
log.Fatal(err)
}
}
func Query(collection string, vec []float64) []string {
payload := map[string]interface{}{
"embedding": vec,
"n_results": 3,
}
data, _ := json.Marshal(payload)
url := fmt.Sprintf("%s/api/v1/collections/%s/query", chromaURL, collection)
resp, err := http.Post(url, "application/json", bytes.NewReader(data))
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
var result struct {
Documents [][]string `json:"documents"`
}
json.NewDecoder(resp.Body).Decode(&result)
if len(result.Documents) > 0 {
return result.Documents[0]
}
return []string{}
}
🧠 Sample: prompt.go
package prompt
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"strings"
)
func Build(query string, contexts []string) string {
contextStr := strings.Join(contexts, "\n")
return fmt.Sprintf("Answer the question based on the context:\n\n%s\n\nQuestion: %s", contextStr, query)
}
func CallOllama(model, prompt string) string {
payload := map[string]string{
"model": model,
"prompt": prompt,
}
body, _ := json.Marshal(payload)
resp, err := http.Post("http://localhost:11434/api/generate", "application/json", bytes.NewBuffer(body))
if err != nil {
panic(err)
}
defer resp.Body.Close()
var out struct {
Response string `json:"response"`
}
json.NewDecoder(resp.Body).Decode(&out)
return out.Response
}
🧪 Running It
-
Start ChromaDB:
chroma run --path ./chroma-data
-
Start Ollama:
ollama run mistral
-
Run your Go program:
go run main.go
📌 Next Steps
- Add PDF/Markdown ingestion using
github.com/ledongthuc/pdf
orblackfriday
- Switch to LlamaIndex or LangChain via REST API for rapid prototyping
- Store user feedback to improve answers
- Build a simple web UI with Go + Svelte/React
Comments |0|
Category: 似水流年