diff --git a/solutions/6a02e23da6fe2e4ac16acf65/solution.py b/solutions/6a02e23da6fe2e4ac16acf65/solution.py index b12048d..10eebc5 100644 --- a/solutions/6a02e23da6fe2e4ac16acf65/solution.py +++ b/solutions/6a02e23da6fe2e4ac16acf65/solution.py @@ -1,23 +1,21 @@ -from langchain_openai import ChatOpenAI -from pydantic import SecretStr -from langchain.tools import tool +from pathlib import Path +import sys + +from langchain_ollama import Ollama, OllamaEmbeddings from langchain_qdrant import QdrantVectorStore from qdrant_client import QdrantClient from qdrant_client.http.models import Distance, VectorParams -from langchain_ollama import OllamaEmbeddings -from langchain_core.documents import Document from langchain_text_splitters import RecursiveCharacterTextSplitter +from langchain.tools import tool from langchain.agents import create_agent +from langchain_core.documents import Document -# ---------- LLM ---------- -llm = ChatOpenAI( - model="openai/gpt-oss-20b", - base_url='https://platform.brojs.ru/jrnl-bh/api/inference/v1', - api_key=SecretStr("jrnl_30283ab953615cbb6846ff9940a1eedce0b76d7b2f59a2394f29e74643e6a90d"), +# ---------- LLM and embeddings ---------- +llm = Ollama( + model="llama3", # local Ollama model temperature=0.7, ) -# ---------- Embeddings ---------- embeddings = OllamaEmbeddings(model="nomic-embed-text") # ---------- Qdrant client ---------- @@ -26,83 +24,99 @@ client.create_collection( collection_name="knowledge_base", vectors_config=VectorParams(size=embeddings.embedding_size, distance=Distance.COSINE), ) -vector_store = QdrantVectorStore( - client=client, - collection_name="knowledge_base", - embedding=embeddings, -) +vector_store = QdrantVectorStore(client=client, collection_name="knowledge_base", embedding=embeddings) # ---------- Text splitter ---------- -splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100) +splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50) # ---------- Tools ---------- @tool def search_knowledge_base(query: str, max_results: int = 5) -> str: """Search the knowledge base for relevant documents.""" - docs_with_score = vector_store.similarity_search_with_score(query, k=max_results) - if not docs_with_score: - return "No results found." - result_lines = [ - f"{i+1}. {doc.page_content[:200]}..." for i, (doc, _) in enumerate(docs_with_score) - ] - return "\n".join(result_lines) + results = vector_store.similarity_search_with_score(query, k=max_results) + if not results: + return "No relevant information found." + out_lines = [] + for doc, score in results: + title = doc.metadata.get("title", "Untitled") + content_preview = doc.page_content[:200] + ("..." if len(doc.page_content) > 200 else "") + out_lines.append(f"Score: {score:.3f}\nTitle: {title}\nContent: {content_preview}") + return "\n\n".join(out_lines) @tool -def add_to_knowledge_base(content: str, title: str) -> str: +def add_to_knowledge_base(content: str, title: str = "Untitled") -> str: """Add a new document to the knowledge base.""" chunks = splitter.split_text(content) - documents = [Document(page_content=chunk, metadata={"title": title}) for chunk in chunks] + documents = [ + Document(page_content=chunk, metadata={"title": f"{title} (part {i+1})"}) + for i, chunk in enumerate(chunks) + ] vector_store.add_documents(documents) - return f"Added {len(documents)} chunks from '{title}'." + return f"Added {len(chunks)} chunks to the knowledge base under title '{title}'." # ---------- Agent ---------- +system_prompt = """ +You are an assistant that can search and add information to a local knowledge base. +Use the tools `search_knowledge_base` and `add_to_knowledge_base` as needed. +""" + agent = create_agent( model=llm, tools=[search_knowledge_base, add_to_knowledge_base], - system_prompt="You are an assistant that can search and add documents to the knowledge base.", + system_prompt=system_prompt, ) # ---------- CLI ---------- +def load_documents_from_dir(directory: Path): + for file_path in directory.rglob("*"): + if file_path.is_file() and file_path.suffix.lower() in {".txt", ".md"}: + content = file_path.read_text(encoding="utf-8") + title = file_path.stem + add_to_knowledge_base(content=content, title=title) + def main(): - print("RAG Agent CLI. Commands: /add