Skip to content

Commit

Permalink
chore!: rename Langchain integrations and improve descriptions
Browse files Browse the repository at this point in the history
This add "Search" in the names of the Langchain integrations, to make
explicit that they rely on the "search" entrypoint of Linkup, and make
possible the addition of future integrations relying on other
entrypoints, like a `LinkupContentTool`.
  • Loading branch information
cjumel committed Nov 26, 2024
1 parent 4e70686 commit 4829bc7
Show file tree
Hide file tree
Showing 10 changed files with 60 additions and 56 deletions.
28 changes: 15 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,20 @@ pip install langchain-linkup

```python
import os
from langchain_linkup import LinkupRetriever
from langchain_linkup import LinkupSearchRetriever

os.environ["LINKUP_API_KEY"] = "YOUR_LINKUP_API_KEY"
# or dotenv.load_dotenv()
retriever = LinkupRetriever(...)
retriever = LinkupSearchRetriever(...)
...
```

Option 3: Pass the Linkup API key to the Linkup LangChain component when creating it.

```python
from langchain_linkup import LinkupRetriever
from langchain_linkup import LinkupSearchRetriever

retriever = LinkupRetriever(api_key="YOUR_LINKUP_API_KEY", ...)
retriever = LinkupSearchRetriever(api_key="YOUR_LINKUP_API_KEY", ...)
...
```

Expand All @@ -73,18 +73,19 @@ All search queries can be used with two very different modes:
but it will be able to solve more complex queries (e.g. "What is the company profile of LangChain
accross the last few years, and how does it compare to its concurrents?")

### 🔍 Retriever
### 🔍 Linkup Search Retriever

A retriever is a LangChain component which simply retrieves documents based on a query. It is
typically the first step of a RAG (Retrival Augmented Generation) pipeline. See
[this page](https://python.langchain.com/docs/concepts/retrievers/) for more information.
[this page](https://python.langchain.com/docs/concepts/retrievers/) for more information. The
`LinkupSearchRetriever` makes available the Linkup API search as a LangChain retriever.

```python
from langchain_linkup import LinkupRetriever
from langchain_linkup import LinkupSearchRetriever

# Initialize the LangChain component (API key can be read from the environment variable or passed as
# an argument)
retriever = LinkupRetriever(
retriever = LinkupSearchRetriever(
depth="deep", # "standard" or "deep"
)

Expand All @@ -93,19 +94,20 @@ documents = retriever.invoke(input="What is Linkup, the new French AI startup?")
print(documents)
```

### ⚒️ Tool
### ⚒️ Linkup Search Tool

A tool is a LangChain component which enables agents to perform a specific task, like a web search.
Tools are designed to be called autonomously by the agent, and their output is fed back to the
agent, allowing them to perform some kind of reasoning based on the tool usage. See
[this page](https://python.langchain.com/docs/integrations/tools/) for more information.
[this page](https://python.langchain.com/docs/integrations/tools/) for more information. The
`LinkupSearchTool` makes available the Linkup API search as a LangChain tool.

```python
from langchain_linkup import LinkupTool
from langchain_linkup import LinkupSearchTool

# Initialize the LangChain component (API key can be read from the environment variable or passed as
# an argument)
tool = LinkupTool(
tool = LinkupSearchTool(
depth="deep", # "standard" or "deep"
output_type="searchResults", # "searchResults", "sourcedAnswer" or "structured"
)
Expand All @@ -118,4 +120,4 @@ print(search_results)
### 📚 More Examples

See the `examples/` directory for more contextualized examples and documentation, for instance on
how to use the Linkup retriever in a simple RAG pipeline.
how to use the Linkup Search Retriever in a simple RAG pipeline.
12 changes: 6 additions & 6 deletions examples/1_rag.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
`requirements-dev.txt` file (you can run `pip install -r requirements-dev.txt` to install them).
Additionally, you need an API key for Linkup, and another one for OpenAI (for the final generation),
which you can set manually as the LINKUP_API_KEY and OPENAI_API_KEY environment variables, or you
can duplicate the file `.env.example` in a `.env` file, fill the missing values, and the environment
variables will be automatically loaded from it, or you can replace the corresponding variables
below.
which you can set manually as the `LINKUP_API_KEY` and `OPENAI_API_KEY` environment variables, or
you can duplicate the file `.env.example` in a `.env` file, fill the missing values, and the
environment variables will be automatically loaded from it, or you can replace the corresponding
variables below.
"""

from typing import Any, Literal
Expand All @@ -19,7 +19,7 @@
from langchain_core.runnables import Runnable, RunnableLambda, RunnablePassthrough
from langchain_openai import ChatOpenAI

from langchain_linkup import LinkupRetriever
from langchain_linkup import LinkupSearchRetriever

# You can change the RAG query and parameters here. If you prefer not to use environment variables
# you can fill them here.
Expand All @@ -31,7 +31,7 @@

load_dotenv() # Load environment variables from .env file if there is one

retriever = LinkupRetriever(linkup_api_key=linkup_api_key, depth=linkup_depth)
retriever = LinkupSearchRetriever(linkup_api_key=linkup_api_key, depth=linkup_depth)


def format_retrieved_documents(docs: list[Document]) -> str:
Expand Down
12 changes: 6 additions & 6 deletions examples/2_search_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
`requirements-dev.txt` file (you can run `pip install -r requirements-dev.txt` to install them).
Additionally, you need an API key for Linkup, and another one for OpenAI (for the base agent model),
which you can set manually as the LINKUP_API_KEY and OPENAI_API_KEY environment variables, or you
can duplicate the file `.env.example` in a `.env` file, fill the missing values, and the environment
variables will be automatically loaded from it, or you can replace the corresponding variables
below.
which you can set manually as the `LINKUP_API_KEY` and `OPENAI_API_KEY` environment variables, or
you can duplicate the file `.env.example` in a `.env` file, fill the missing values, and the
environment variables will be automatically loaded from it, or you can replace the corresponding
variables below.
"""

from typing import Literal
Expand All @@ -20,7 +20,7 @@
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

from langchain_linkup import LinkupTool
from langchain_linkup import LinkupSearchTool

# You can change the RAG query and parameters here. If you prefer not to use environment variables
# you can fill them here.
Expand All @@ -33,7 +33,7 @@
load_dotenv() # Load environment variables from .env file if there is one

model = ChatOpenAI(model=openai_model, api_key=openai_api_key)
search_tool = LinkupTool(depth="standard", output_type="searchResults")
search_tool = LinkupSearchTool(depth="standard", output_type="searchResults")
agent_executor = create_react_agent(model=model, tools=[search_tool])

# Use the agent
Expand Down
8 changes: 4 additions & 4 deletions langchain_linkup/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .retriever import LinkupRetriever
from .tool import LinkupTool
from .search_retriever import LinkupSearchRetriever
from .search_tool import LinkupSearchTool

__all__ = [
"LinkupRetriever",
"LinkupTool",
"LinkupSearchRetriever",
"LinkupSearchTool",
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
from linkup import LinkupClient, LinkupSearchResults


class LinkupRetriever(BaseRetriever):
"""A retriever which using the Linkup API to retrieve documents.
class LinkupSearchRetriever(BaseRetriever):
"""A retriever using the Linkup API search to retrieve documents using natural language.
This retriever is a wrapper around the Linkup API, allowing you to search for documents from
the Linkup API sources, that is the web and the Linkup Premium Partner sources.
This retriever is a wrapper around the Linkup API search entrypoint, making possible to
retrieve documents from the Linkup API sources, that is the web and the Linkup Premium Partner
sources, using natural language.
"""

depth: Literal["standard", "deep"]
Expand Down
19 changes: 10 additions & 9 deletions langchain_linkup/tool.py → langchain_linkup/search_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@
from pydantic import BaseModel, Field


class LinkupInput(BaseModel):
query: str = Field(description="The search query.")
class LinkupSearchInput(BaseModel):
query: str = Field(description="The query for the Linkup API search.")


class LinkupTool(BaseTool):
"""A tool to query the Linkup API in agentic workflows.
class LinkupSearchTool(BaseTool):
"""A tool to query the Linkup API search in natural language.
This tool is a wrapper around the Linkup API, allowing you to search for documents from the
Linkup API sources, that is the web and the Linkup Premium Partner sources.
This tool is a wrapper around the Linkup API search entrypoint, making possible to perform
search queries based on the Linkup API sources, that is the web and the Linkup Premium Partner
sources, using natural language.
"""

depth: Literal["standard", "deep"]
Expand All @@ -39,10 +40,10 @@ class LinkupTool(BaseTool):
# Fields used by the agent to describe how to use the tool under the hood
name: str = "linkup"
description: str = (
"A tool to search for information using the Linkup API, that is from the "
"web and Linkup Premium Partner sources. "
"A tool to perform search queries based on the Linkup API sources, that is the web and the "
"Linkup Premium Partner sources, using natural language."
)
args_schema: Type[BaseModel] = LinkupInput
args_schema: Type[BaseModel] = LinkupSearchInput
return_direct: bool = False

def _run(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import pytest
from langchain_core.documents import Document

from langchain_linkup import LinkupRetriever
from langchain_linkup import LinkupSearchRetriever

# NOTE: there is no retriever integration in langchain-tests to this date (version 0.3.4), so we
# need to implement tests manually


def test_get_relevant_document(linkup_api_key: str) -> None:
retriever = LinkupRetriever(linkup_api_key=linkup_api_key, depth="standard")
retriever = LinkupSearchRetriever(linkup_api_key=linkup_api_key, depth="standard")
documents: list[Document] = retriever.invoke(input="What is Linkup, the new French AI startup?")

assert isinstance(documents, list) and documents
Expand All @@ -21,7 +21,7 @@ def test_get_relevant_document(linkup_api_key: str) -> None:

@pytest.mark.asyncio
async def test_aget_relevant_documents(linkup_api_key: str) -> None:
retriever = LinkupRetriever(linkup_api_key=linkup_api_key, depth="standard")
retriever = LinkupSearchRetriever(linkup_api_key=linkup_api_key, depth="standard")
documents: list[Document] = await retriever.ainvoke(
input="What is Linkup, the new French AI startup?"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
from dotenv import load_dotenv
from langchain_tests.integration_tests import ToolsIntegrationTests

from langchain_linkup import LinkupTool
from langchain_linkup import LinkupSearchTool


class TestLinkupToolIntegration(ToolsIntegrationTests):
class TestLinkupSearchToolIntegration(ToolsIntegrationTests):
@property
def tool_constructor(self) -> Type[LinkupTool]:
return LinkupTool
def tool_constructor(self) -> Type[LinkupSearchTool]:
return LinkupSearchTool

@property
def tool_constructor_params(self) -> dict[str, Any]:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from langchain_core.documents import Document
from pytest_mock import MockerFixture

from langchain_linkup import LinkupRetriever
from langchain_linkup import LinkupSearchRetriever

# NOTE: there is no retriever integration in langchain-tests to this date (version 0.3.4), so we
# need to implement tests manually
Expand Down Expand Up @@ -34,7 +34,7 @@ def test_get_relevant_document(mocker: MockerFixture, linkup_api_key: str) -> No
),
)

retriever = LinkupRetriever(linkup_api_key=linkup_api_key, depth="standard")
retriever = LinkupSearchRetriever(linkup_api_key=linkup_api_key, depth="standard")
documents: list[Document] = retriever.invoke(input="What is Linkup, the new French AI startup?")

assert len(documents) == 2
Expand Down Expand Up @@ -82,7 +82,7 @@ async def test_aget_relevant_documents(mocker: MockerFixture, linkup_api_key: st
),
)

retriever = LinkupRetriever(linkup_api_key=linkup_api_key, depth="standard")
retriever = LinkupSearchRetriever(linkup_api_key=linkup_api_key, depth="standard")
documents: list[Document] = await retriever.ainvoke(
input="What is Linkup, the new French AI startup?"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

from langchain_tests.unit_tests import ToolsUnitTests

from langchain_linkup import LinkupTool
from langchain_linkup import LinkupSearchTool


class TestLinkupToolUnit(ToolsUnitTests):
class TestLinkupSearchToolUnit(ToolsUnitTests):
@property
def tool_constructor(self) -> Type[LinkupTool]:
return LinkupTool
def tool_constructor(self) -> Type[LinkupSearchTool]:
return LinkupSearchTool

@property
def tool_constructor_params(self) -> dict[str, Any]:
Expand Down

0 comments on commit 4829bc7

Please sign in to comment.