# LangChain Retriever Integration

LDR now supports using any LangChain retriever as a search engine. This allows you to use vector stores, databases, or any custom retriever implementation with LDR's research capabilities.

## Quick Start

```python
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from local_deep_research.api import quick_summary

# Create your retriever (any LangChain retriever works)
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(documents, embeddings)
retriever = vectorstore.as_retriever()

# Use with LDR
result = quick_summary(
    query="What are our deployment procedures?",
    retrievers={"company_kb": retriever},
    search_tool="company_kb"
)
```

## How It Works

1. Pass retrievers as a dictionary to any research function
2. Each retriever gets a name (the dictionary key)
3. Use the retriever by setting `search_tool` to its name
4. Retrievers work exactly like built-in search engines

## Usage Examples

### Single Retriever

```python
result = quick_summary(
    query="Your question",
    retrievers={"my_kb": retriever},
    search_tool="my_kb"  # Use only this retriever
)
```

### Multiple Retrievers

```python
result = detailed_research(
    query="Complex question",
    retrievers={
        "vector_db": vector_retriever,
        "graph_db": graph_retriever,
        "sql_db": sql_retriever
    },
    search_tool="vector_db"  # Primary retriever; with the default
    # langgraph-agent strategy, every registered retriever is also
    # exposed to the research agent as a search tool
)
```

### Hybrid Search (Retriever + Web)

```python
result = quick_summary(
    query="Compare internal and external practices",
    retrievers={"internal": internal_retriever},
    search_tool="searxng"  # Web engine as primary; the langgraph-agent
    # strategy can also query the registered "internal" retriever
)
```

### Selective Usage

```python
# Pass multiple retrievers but use only one
all_retrievers = {
    "tech_docs": tech_retriever,
    "legal_docs": legal_retriever,
    "hr_docs": hr_retriever
}

# Use only tech docs for this query
result = quick_summary(
    query="Technical question",
    retrievers=all_retrievers,
    search_tool="tech_docs"  # Select specific retriever
)
```

## Supported Retrievers

Any LangChain `BaseRetriever` implementation works:

- **Vector Stores**: FAISS, Chroma, Pinecone, Weaviate, Qdrant, etc.
- **Cloud Services**: Vertex AI, AWS Bedrock, Azure Cognitive Search
- **Databases**: PostgreSQL, MongoDB, Elasticsearch
- **Custom**: Any class inheriting from `BaseRetriever`

## API Reference

### Parameters

All research functions (`quick_summary`, `detailed_research`, `generate_report`) accept:

- `retrievers`: Optional[Dict[str, BaseRetriever]] - Dictionary of retrievers
- `search_tool`: str - Name of the retriever (or built-in engine) to use as the primary search source

### Example with Complex Setup

```python
from langchain.vectorstores import VertexAIVectorSearch
from langchain.embeddings import VertexAIEmbeddings
import os

# User handles proxy/auth setup
os.environ["HTTP_PROXY"] = "http://proxy.company.com:8080"

# Create retriever with complex configuration
embeddings = VertexAIEmbeddings(
    project="my-project",
    location="us-central1"
)
vectorstore = VertexAIVectorSearch(
    project="my-project",
    location="us-central1",
    index="my-index",
    endpoint="my-endpoint",
    embeddings=embeddings
)
retriever = vectorstore.as_retriever()

# Use with LDR - all complexity is hidden
result = quick_summary(
    query="Internal knowledge query",
    retrievers={"vertex_ai": retriever},
    search_tool="vertex_ai"
)
```

## Benefits

1. **Zero Coupling**: LDR doesn't need to know retriever internals
2. **Full Compatibility**: Works with all LDR features (strategies, agentic engine selection, etc.)
3. **Clean API**: Just pass a dictionary of retrievers
4. **Flexible**: Mix retrievers with web search seamlessly

## Testing Your Integration

```python
from langchain.schema import Document, BaseRetriever

class TestRetriever(BaseRetriever):
    def get_relevant_documents(self, query: str):
        return [Document(page_content=f"Test doc about {query}")]

    async def aget_relevant_documents(self, query: str):
        return self.get_relevant_documents(query)

# Test it
result = quick_summary(
    query="test",
    retrievers={"test": TestRetriever()},
    search_tool="test"
)
```
