日本語はまだ勉強中ですから、変などころあったら、ぜひコメントしてください。
RAGとは
RAGはRetrieval augmented generationの略です。
大規模言語モデル内容を生成する前に、promptによる外部のデーターベースに知識を検索、元のpromptと組み合わせて、アウトプットを改善するための技術です。
例えば:
ユーザ:
今日の注目の新聞は何ですか?
Gemini:
今日の注目の新聞記事については、リアルタイムで変化するため、特定の新聞社名を挙げて「今日の注目の記事はこれです」と断言することは難しいです。
ChatGPT:
本日(2024年11月6日)の日本の注目ニュースは次のような内容が含まれている可能性があります:
アメリカ大統領選挙の最新動向 - 特に若い世代の投票行動や政策への関心が注目されています。
国内経済とインフレの動き - 日本の物価高騰が続き、家計への影響や政府の対応が議論されています。
アジアの地政学的緊張 - 日本周辺地域の安全保障に関連する動向が続いています。
以上の内容が注目ニュースとして考えられますが、詳細については直接ニュースソースで確認されるとよいでしょう。
geminiはリアルタイムによっての内容は回答できません。
chatgptはRAGか、Function Callingか、どちらかを使っていると思います。
今回はgolang+langchaingo+ollama+qdrantでRAGを実験してみます。
準備
ollamaをインストール
curl -fsSL https://ollama.com/install.sh | sh
qdrantのコンテナを実行
mkdir -p ~/.config/qdrantdocker run -p 6333:6333 -p 6334:6334 \ -v ~/.config/qdrant:/qdrant/storage:z \ qdrant/qdrant
bge-large-en-v1.5をollamaで実行
知識をベクトルデータベースに保存するにはText Embedingモデルが必要です。今回はbge-large-en-v1.5を使うことになりました。
ollamaのモデルライブラリにはbge-large-en-v1.5がありませんので、bge-large-en-v1.5をGGUFに変換することが必要です。
git-lfsとcmakeをインストール
sudo apt install git-lfs cmakegit lfs installgit clone https://huggingface.co/BAAI/bge-large-en-v1.5
llama.cppをクローン
git clone https://github.com/ggerganov/llama.cpp.gitcd llama.cpp/# python仮想環境はおすすめですsudo apt install python3.12-venvpython3 -m venv python-venv./python-venv/bin/pip3 install -r requirements.txt
GGUFに変換
./llama.cpp/python-venv/bin/python3 ./llama.cpp/convert_hf_to_gguf.py ./bge-large-en-v1.5/cd bge-large-en-v1.5/echo "FROM ./bge-large-en-v1.5-F16.gguf" > Modelfileollama create bge-large-en-v1.5-F16 -f Modelfile# embedingモデルはollamaで直接実行はできませんです# Error: "bge-large-en-v1.5-F16" does not support generate# ここは試してみてだけですollama run bge-large-en-v1.5-F16
Qwen2.5をollamaで実行
# 32bは20GBのGPUメモリ(VRAM)が必要です# CPUもできるですが、非常に重いですから# 3bや7bや14bなどもぜひ使ってみてくださいollama run qwen2.5:32b-instruct
実現
text embedder
package main import ( "net/url" "github.com/tmc/langchaingo/embeddings" "github.com/tmc/langchaingo/llms/ollama" "github.com/tmc/langchaingo/vectorstores" "github.com/tmc/langchaingo/vectorstores/qdrant") func NewVectorStore() (vectorstores.VectorStore, error) { llm, err := ollama.New( ollama.WithModel("bge-large-en-v1.5-F16"), ollama.WithServerURL("http://localhost:11434"), ) if err != nil { return nil, err } embeder, err := embeddings.NewEmbedder(llm) if err != nil { return nil, err } qu, err := url.Parse("http://localhost:6333") if err != nil { return nil, err } qd, err := qdrant.New( qdrant.WithURL(*qu), qdrant.WithCollectionName("test"), qdrant.WithEmbedder(embeder), ) if err != nil { return nil, err } return qd, nil}
テキストを導入
package main import ( "context" "io" "strings" "github.com/tmc/langchaingo/documentloaders" "github.com/tmc/langchaingo/schema" "github.com/tmc/langchaingo/textsplitter" "github.com/tmc/langchaingo/vectorstores") // TextToChunks テキストを分割func TextToChunks(r io.Reader, chunkSize, chunkOverlap int) ([]schema.Document, error) { // 新たなドキュメンタリーローダーを作成 docLoaded := documentloaders.NewText(r) // テキストを再帰的に分割し方法 split := textsplitter.NewRecursiveCharacter() // 分割サイズを設定 split.ChunkSize = chunkSize // 重なるサイズを設定 split.ChunkOverlap = chunkOverlap // ロードして分割する docs, err := docLoaded.LoadAndSplit(context.Background(), split) if err != nil { return nil, err } return docs, nil} func AddText(qd vectorstores.VectorStore) error { docs, err := TextToChunks(strings.NewReader(`テストテキスト`), 300, 20) if err != nil { return err } // ベクトルデーターベースに導入 _, err = qd.AddDocuments(context.TODO(), docs) if err != nil { return err } return nil}
RAG
知識を検索
package main import ( "context" "github.com/tmc/langchaingo/schema" "github.com/tmc/langchaingo/vectorstores") func RetrieveDocuments(ctx context.Context, qd vectorstores.VectorStore, prompt string) ([]schema.Document, error) { optionsVector := []vectorstores.Option{ vectorstores.WithScoreThreshold(0.80), } retriever := vectorstores.ToRetriever(qd, 10, optionsVector...) docRetrieved, err := retriever.GetRelevantDocuments(ctx, prompt) if err != nil { return nil, err } return docRetrieved, nil}
llmで予測する
package main import ( "context" "fmt" "github.com/tmc/langchaingo/llms" "github.com/tmc/langchaingo/llms/ollama" "github.com/tmc/langchaingo/schema") func GenerateAnswer(ctx context.Context, docRetrieved []schema.Document, prompt string) error { llm, err := ollama.New( ollama.WithModel("qwen2.5:32b-instruct"), ollama.WithServerURL("http://localhost:11434"), ) if err != nil { return err } var msgs []llms.MessageContent for _, doc := range docRetrieved { msgs = append(msgs, llms.TextParts(llms.ChatMessageTypeAI, doc.PageContent)) } msgs = append(msgs, llms.TextParts(llms.ChatMessageTypeHuman, prompt)) _, err = llm.GenerateContent(ctx, msgs, llms.WithTemperature(0.3), llms.WithStreamingFunc(func(ctx context.Context, chunk []byte) error { // 結果をストリームで標準出力に出力して fmt.Print(string(chunk)) return nil }), ) if err != nil { return err } return nil}
0 件のコメント