Files
agent-s-rag-pamyatyu/SOLUTION.md
T
2026-07-01 10:57:34 +03:00

3.6 KiB
Raw Blame History

What was implemented

  • A FastAPI service exposing a single /ask endpoint that accepts a user question and returns an answer together with the sources used.
  • RAG (RetrievalAugmented Generation) logic built with LangChain: documents from data/ are embedded with OpenAI embeddings, stored in a FAISS vector store, and queried by a RetrievalQA chain that feeds the retrieved passages to GPT4.
  • Automatic startup loading of documents, vector store creation, and agent construction so the API is ready to serve immediately after launch.

Why the main parts satisfy the assignment

  • RAG memory: create_vectorstore builds a FAISS index from the loaded documents, and build_agent wires this index into a RetrievalQA chain that retrieves relevant passages before generation.
  • Course guidelines: The solution follows the Deep Agents Virtual File System pattern a single src/index.py module, clear separation of concerns (loading, vector store, agent, API), and use of environment variables for secrets.
  • Python implementation: All code is pure Python 3.11+, uses only standard libraries and welldocumented thirdparty packages (fastapi, langchain, openai, dotenv).
  • Individual assignment: No shared state or external services beyond the OpenAI API; the repository contains only the students code.

Key code excerpts

Loading documents (src/index.py)

def load_documents(path: Path) -> List:
    if not path.exists() or not path.is_dir():
        print(f"Warning: Data directory '{path}' not found. No documents loaded.")
        return []

    loader = DirectoryLoader(str(path), glob="**/*.txt")
    documents = loader.load()
    print(f"Loaded {len(documents)} documents from '{path}'.")
    return documents

Creating the vector store (src/index.py)

def create_vectorstore(documents: List) -> FAISS:
    embeddings = OpenAIEmbeddings()
    vectorstore = FAISS.from_documents(documents, embeddings)
    print("FAISS vector store created.")
    return vectorstore

Building the RetrievalQA agent (src/index.py)

def build_agent(vectorstore: FAISS) -> RetrievalQA:
    llm = OpenAI(model_name="gpt-4", temperature=0, openai_api_key=OPENAI_API_KEY)
    retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
    qa_chain = RetrievalQA.from_chain_type(
        llm=llm,
        chain_type="stuff",
        retriever=retriever,
        return_source_documents=True,
    )
    print("RetrievalQA agent constructed.")
    return qa_chain

FastAPI endpoint (src/index.py)

@app.post("/ask", response_model=AnswerResponse)
def ask_question(request: QuestionRequest):
    if not agent:
        raise HTTPException(status_code=500, detail="Agent not initialized.")
    try:
        result = agent({"question": request.question})
        answer = result.get("answer", "")
        sources = [doc.metadata.get("source", "") for doc in result.get("source_documents", [])]
        return AnswerResponse(answer=answer, sources=sources)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

Honest limitations

  • The vector store is rebuilt on every server restart; no persistence across restarts.
  • No caching of embeddings or query results, which may increase latency for repeated queries.
  • Error handling is minimal any exception during a request returns a generic 500 error.
  • The solution assumes all documents are plain .txt; other formats would need additional loaders.

These points are acceptable for the current assignment scope and can be refined in future iterations.