ДОбился запуска
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
__pycache__
|
||||
agent_env
|
||||
.lock
|
||||
.sqlite
|
||||
qdrant_data
|
||||
qdrant_storage
|
||||
@@ -1,15 +1,13 @@
|
||||
from typing import TypedDict, List, Optional, Annotated
|
||||
import operator
|
||||
from langchain_community.llms import Ollama
|
||||
from langchain_community.embeddings import OllamaEmbeddings
|
||||
from langchain_community.vectorstores import Qdrant
|
||||
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
||||
from langchain_community.document_loaders import DirectoryLoader, PyPDFLoader
|
||||
from langgraph.graph import StateGraph, END
|
||||
from langgraph.graph.message import add_messages
|
||||
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
|
||||
from langchain_core.messages import AIMessage, SystemMessage
|
||||
from langchain.tools import tool
|
||||
from langchain.agents import AgentExecutor, create_react_agent
|
||||
# from langchain.agents import AgentExecutor, create_react_agent
|
||||
import numpy as np
|
||||
|
||||
# Определяем состояние агента
|
||||
@@ -22,16 +20,11 @@ class AgentState(TypedDict):
|
||||
|
||||
# Инициализация LLM через Ollama
|
||||
llm = Ollama(
|
||||
model="llama3.2:3b",
|
||||
model="qwen2.5-coder-16k:14b",
|
||||
temperature=0.1, # Низкая температура для консистентности
|
||||
num_predict=1024, # Максимальная длина ответа
|
||||
)
|
||||
|
||||
# Инициализация эмбеддингов
|
||||
embeddings = OllamaEmbeddings(
|
||||
model="nomic-embed-text", # Хорошие локальные эмбеддинги
|
||||
)
|
||||
|
||||
# Создаем инструменты для агента
|
||||
@tool
|
||||
def search_knowledge_base(query: str) -> str:
|
||||
@@ -127,6 +120,3 @@ def create_agent_graph():
|
||||
workflow.add_edge("generate", END)
|
||||
|
||||
return workflow.compile()
|
||||
|
||||
# Создаем и компилируем граф
|
||||
agent_graph = create_agent_graph()
|
||||
@@ -1,6 +1,10 @@
|
||||
import gradio as gr
|
||||
import asyncio
|
||||
import os
|
||||
from typing import List
|
||||
from agent_core import create_agent_graph
|
||||
from local_knowledge_base import LocalKnowledgeBase
|
||||
from langchain_core.messages import HumanMessage
|
||||
|
||||
class AgenticRAGInterface:
|
||||
def __init__(self, agent_graph, knowledge_base):
|
||||
@@ -61,8 +65,15 @@ class AgenticRAGInterface:
|
||||
self.conversation_history = []
|
||||
return "История очищена", ""
|
||||
|
||||
# Инициализируем базу
|
||||
kb = LocalKnowledgeBase()
|
||||
# Загружаем документы (если есть)
|
||||
if os.path.exists("./documents"):
|
||||
kb.load_documents("./documents")
|
||||
|
||||
|
||||
# Создаем интерфейс
|
||||
interface = AgenticRAGInterface(agent_graph, kb)
|
||||
interface = AgenticRAGInterface(create_agent_graph(), kb)
|
||||
|
||||
# Создаем Gradio интерфейс
|
||||
def create_gradio_interface():
|
||||
|
||||
@@ -1,19 +1,28 @@
|
||||
import os
|
||||
from qdrant_client import QdrantClient
|
||||
from qdrant_client.models import Distance, VectorParams, PointStruct
|
||||
from langchain_community.document_loaders import TextLoader, PyPDFLoader, DirectoryLoader
|
||||
from langchain.text_splitter import Language
|
||||
from langchain_community.document_loaders import (
|
||||
TextLoader,
|
||||
PyPDFLoader,
|
||||
DirectoryLoader,
|
||||
)
|
||||
from langchain_text_splitters import Language, RecursiveCharacterTextSplitter
|
||||
from langchain_community.embeddings import OllamaEmbeddings
|
||||
|
||||
|
||||
class LocalKnowledgeBase:
|
||||
def __init__(self, collection_name="documents", persist_dir="./qdrant_data"):
|
||||
# Инициализируем клиент Qdrant
|
||||
self.client = QdrantClient(
|
||||
path=persist_dir, # Локальное хранение
|
||||
prefer_grpc=True
|
||||
path=persist_dir, prefer_grpc=True # Локальное хранение
|
||||
)
|
||||
|
||||
self.collection_name = collection_name
|
||||
self.embeddings = embeddings
|
||||
|
||||
# Инициализация эмбеддингов
|
||||
self.embeddings = OllamaEmbeddings(
|
||||
model="nomic-embed-text", # Хорошие локальные эмбеддинги
|
||||
)
|
||||
|
||||
# Создаем коллекцию если её нет
|
||||
self._create_collection()
|
||||
@@ -28,22 +37,21 @@ class LocalKnowledgeBase:
|
||||
collection_name=self.collection_name,
|
||||
vectors_config=VectorParams(
|
||||
size=768, # Размерность эмбеддингов nomic-embed-text
|
||||
distance=Distance.COSINE
|
||||
)
|
||||
distance=Distance.COSINE,
|
||||
),
|
||||
)
|
||||
print(f"Создана коллекция {self.collection_name}")
|
||||
|
||||
def load_documents(self, directory_path: str):
|
||||
"""Загрузка документов из директории"""
|
||||
loaders = {
|
||||
'.pdf': PyPDFLoader,
|
||||
'.txt': lambda path: DirectoryLoader(path, glob="**/*.txt"),
|
||||
'.docx': lambda path: DirectoryLoader(path, glob="**/*.docx"),
|
||||
'.hpp': lambda path: TextLoader(path, encoding='utf-8'),
|
||||
'.cpp': lambda path: TextLoader(path, encoding='utf-8'), # добавить
|
||||
'.h': lambda path: TextLoader(path, encoding='utf-8'), # добавить
|
||||
'.cc': lambda path: TextLoader(path, encoding='utf-8'), # добавить
|
||||
|
||||
".pdf": PyPDFLoader,
|
||||
".txt": lambda path: DirectoryLoader(path, glob="**/*.txt"),
|
||||
".docx": lambda path: DirectoryLoader(path, glob="**/*.docx"),
|
||||
".hpp": lambda path: TextLoader(path, encoding="utf-8"),
|
||||
".cpp": lambda path: TextLoader(path, encoding="utf-8"), # добавить
|
||||
".h": lambda path: TextLoader(path, encoding="utf-8"), # добавить
|
||||
".cc": lambda path: TextLoader(path, encoding="utf-8"), # добавить
|
||||
}
|
||||
|
||||
all_documents = []
|
||||
@@ -65,7 +73,7 @@ class LocalKnowledgeBase:
|
||||
language=Language.CPP,
|
||||
chunk_size=1000,
|
||||
chunk_overlap=200,
|
||||
length_function=len
|
||||
length_function=len,
|
||||
)
|
||||
|
||||
chunks = text_splitter.split_documents(all_documents)
|
||||
@@ -91,26 +99,20 @@ class LocalKnowledgeBase:
|
||||
"text": doc.page_content,
|
||||
"source": doc.metadata.get("source", "unknown"),
|
||||
"page": doc.metadata.get("page", 0),
|
||||
"file_type": "cpp"
|
||||
}
|
||||
"file_type": "cpp",
|
||||
},
|
||||
)
|
||||
points.append(point)
|
||||
|
||||
# Пакетная загрузка каждые 100 точек
|
||||
if len(points) >= 100:
|
||||
self.client.upsert(
|
||||
collection_name=self.collection_name,
|
||||
points=points
|
||||
)
|
||||
self.client.upsert(collection_name=self.collection_name, points=points)
|
||||
points = []
|
||||
print(f"Индексировано {i+1} документов")
|
||||
|
||||
# Загружаем оставшиеся
|
||||
if points:
|
||||
self.client.upsert(
|
||||
collection_name=self.collection_name,
|
||||
points=points
|
||||
)
|
||||
self.client.upsert(collection_name=self.collection_name, points=points)
|
||||
|
||||
print(f"Индексация завершена. Всего документов: {len(documents)}")
|
||||
|
||||
@@ -120,26 +122,22 @@ class LocalKnowledgeBase:
|
||||
query_embedding = self.embeddings.embed_query(query)
|
||||
|
||||
# Ищем в Qdrant
|
||||
search_result = self.client.search(
|
||||
search_result = self.client.query_points(
|
||||
collection_name=self.collection_name,
|
||||
query_vector=query_embedding,
|
||||
limit=top_k
|
||||
query=query_embedding,
|
||||
limit=top_k,
|
||||
)
|
||||
|
||||
# Форматируем результаты
|
||||
results = []
|
||||
for hit in search_result:
|
||||
results.append({
|
||||
"text": hit.payload["text"],
|
||||
"score": hit.score,
|
||||
"source": hit.payload.get("source", "unknown")
|
||||
})
|
||||
for hit in search_result.points:
|
||||
results.append(
|
||||
{
|
||||
"text": hit.payload["text"],
|
||||
"score": hit.score,
|
||||
"source": hit.payload.get("source", "unknown"),
|
||||
}
|
||||
)
|
||||
|
||||
return results
|
||||
|
||||
# Инициализируем базу знаний
|
||||
kb = LocalKnowledgeBase()
|
||||
|
||||
# Загружаем документы (если есть)
|
||||
if os.path.exists("./documents"):
|
||||
kb.load_documents("./documents")
|
||||
Reference in New Issue
Block a user