langchain-ceramic 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- langchain_ceramic-0.1.0/PKG-INFO +111 -0
- langchain_ceramic-0.1.0/README.md +90 -0
- langchain_ceramic-0.1.0/langchain_ceramic/__init__.py +4 -0
- langchain_ceramic-0.1.0/langchain_ceramic/py.typed +0 -0
- langchain_ceramic-0.1.0/langchain_ceramic/retrievers.py +78 -0
- langchain_ceramic-0.1.0/langchain_ceramic/tools.py +73 -0
- langchain_ceramic-0.1.0/pyproject.toml +33 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: langchain-ceramic
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: An integration package connecting Ceramic and LangChain
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: Ceramic Team
|
|
7
|
+
Author-email: info@ceramic.ai
|
|
8
|
+
Requires-Python: >=3.10,<4.0
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Requires-Dist: ceramic-ai (>=0.1.0)
|
|
17
|
+
Requires-Dist: langchain-core (>=0.3.0,<1.0.0)
|
|
18
|
+
Project-URL: Repository, https://github.com/CeramicTeam/langchain-ceramic
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# LangChain Ceramic
|
|
22
|
+
|
|
23
|
+
LangChain integration for [Ceramic](https://ceramic.ai) — a web search API built for LLMs.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install langchain-ceramic
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Setup
|
|
32
|
+
|
|
33
|
+
Generate an API key at [platform.ceramic.ai/keys](https://platform.ceramic.ai/keys), then export it:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
export CERAMIC_API_KEY="your-api-key"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Or pass it directly when constructing the retriever or tool.
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
### CeramicRetriever in a RAG chain
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from langchain_ceramic import CeramicRetriever
|
|
47
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
48
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
49
|
+
from langchain_core.runnables import RunnablePassthrough
|
|
50
|
+
from langchain_openai import ChatOpenAI
|
|
51
|
+
|
|
52
|
+
retriever = CeramicRetriever(k=5) # reads CERAMIC_API_KEY from env
|
|
53
|
+
|
|
54
|
+
prompt = ChatPromptTemplate.from_template(
|
|
55
|
+
"Answer the question based only on the following context:\n\n{context}\n\nQuestion: {question}"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
chain = (
|
|
59
|
+
{"context": retriever, "question": RunnablePassthrough()}
|
|
60
|
+
| prompt
|
|
61
|
+
| ChatOpenAI(model="gpt-5.5")
|
|
62
|
+
| StrOutputParser()
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
answer = chain.invoke("What are the latest AI chip export restrictions?")
|
|
66
|
+
print(answer)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Each retrieved `Document` has:
|
|
70
|
+
- `page_content`: the result description
|
|
71
|
+
- `metadata["title"]`: page title
|
|
72
|
+
- `metadata["url"]`: source URL
|
|
73
|
+
|
|
74
|
+
### CeramicSearch in an agent
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from langchain_ceramic import CeramicSearch
|
|
78
|
+
from langchain_openai import ChatOpenAI
|
|
79
|
+
from langchain.agents import create_agent
|
|
80
|
+
|
|
81
|
+
tools = [CeramicSearch(max_results=5)]
|
|
82
|
+
agent = create_agent(ChatOpenAI(model="gpt-5.5"), tools=tools)
|
|
83
|
+
|
|
84
|
+
result = agent.invoke({"messages": [{"role": "user", "content": "Find recent news about GLP-1 drugs"}]})
|
|
85
|
+
print(result["messages"][-1].content)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Async usage
|
|
89
|
+
|
|
90
|
+
Both `CeramicRetriever` and `CeramicSearch` support async:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
docs = await retriever.ainvoke("California rental laws")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## API reference
|
|
97
|
+
|
|
98
|
+
### `CeramicRetriever`
|
|
99
|
+
|
|
100
|
+
| Parameter | Type | Default | Description |
|
|
101
|
+
|-----------|------|---------|-------------|
|
|
102
|
+
| `api_key` | `str \| None` | `None` | Ceramic API key (falls back to `CERAMIC_API_KEY` env var) |
|
|
103
|
+
| `k` | `int` | `10` | Maximum number of results to return |
|
|
104
|
+
|
|
105
|
+
### `CeramicSearch`
|
|
106
|
+
|
|
107
|
+
| Parameter | Type | Default | Description |
|
|
108
|
+
|-----------|------|---------|-------------|
|
|
109
|
+
| `api_key` | `str \| None` | `None` | Ceramic API key (falls back to `CERAMIC_API_KEY` env var) |
|
|
110
|
+
| `max_results` | `int` | `5` | Maximum number of results to include in the response string |
|
|
111
|
+
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# LangChain Ceramic
|
|
2
|
+
|
|
3
|
+
LangChain integration for [Ceramic](https://ceramic.ai) — a web search API built for LLMs.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install langchain-ceramic
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Generate an API key at [platform.ceramic.ai/keys](https://platform.ceramic.ai/keys), then export it:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
export CERAMIC_API_KEY="your-api-key"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or pass it directly when constructing the retriever or tool.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### CeramicRetriever in a RAG chain
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from langchain_ceramic import CeramicRetriever
|
|
27
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
28
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
29
|
+
from langchain_core.runnables import RunnablePassthrough
|
|
30
|
+
from langchain_openai import ChatOpenAI
|
|
31
|
+
|
|
32
|
+
retriever = CeramicRetriever(k=5) # reads CERAMIC_API_KEY from env
|
|
33
|
+
|
|
34
|
+
prompt = ChatPromptTemplate.from_template(
|
|
35
|
+
"Answer the question based only on the following context:\n\n{context}\n\nQuestion: {question}"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
chain = (
|
|
39
|
+
{"context": retriever, "question": RunnablePassthrough()}
|
|
40
|
+
| prompt
|
|
41
|
+
| ChatOpenAI(model="gpt-5.5")
|
|
42
|
+
| StrOutputParser()
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
answer = chain.invoke("What are the latest AI chip export restrictions?")
|
|
46
|
+
print(answer)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Each retrieved `Document` has:
|
|
50
|
+
- `page_content`: the result description
|
|
51
|
+
- `metadata["title"]`: page title
|
|
52
|
+
- `metadata["url"]`: source URL
|
|
53
|
+
|
|
54
|
+
### CeramicSearch in an agent
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from langchain_ceramic import CeramicSearch
|
|
58
|
+
from langchain_openai import ChatOpenAI
|
|
59
|
+
from langchain.agents import create_agent
|
|
60
|
+
|
|
61
|
+
tools = [CeramicSearch(max_results=5)]
|
|
62
|
+
agent = create_agent(ChatOpenAI(model="gpt-5.5"), tools=tools)
|
|
63
|
+
|
|
64
|
+
result = agent.invoke({"messages": [{"role": "user", "content": "Find recent news about GLP-1 drugs"}]})
|
|
65
|
+
print(result["messages"][-1].content)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Async usage
|
|
69
|
+
|
|
70
|
+
Both `CeramicRetriever` and `CeramicSearch` support async:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
docs = await retriever.ainvoke("California rental laws")
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## API reference
|
|
77
|
+
|
|
78
|
+
### `CeramicRetriever`
|
|
79
|
+
|
|
80
|
+
| Parameter | Type | Default | Description |
|
|
81
|
+
|-----------|------|---------|-------------|
|
|
82
|
+
| `api_key` | `str \| None` | `None` | Ceramic API key (falls back to `CERAMIC_API_KEY` env var) |
|
|
83
|
+
| `k` | `int` | `10` | Maximum number of results to return |
|
|
84
|
+
|
|
85
|
+
### `CeramicSearch`
|
|
86
|
+
|
|
87
|
+
| Parameter | Type | Default | Description |
|
|
88
|
+
|-----------|------|---------|-------------|
|
|
89
|
+
| `api_key` | `str \| None` | `None` | Ceramic API key (falls back to `CERAMIC_API_KEY` env var) |
|
|
90
|
+
| `max_results` | `int` | `5` | Maximum number of results to include in the response string |
|
|
File without changes
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from langchain_core.callbacks import (
|
|
7
|
+
AsyncCallbackManagerForRetrieverRun,
|
|
8
|
+
CallbackManagerForRetrieverRun,
|
|
9
|
+
)
|
|
10
|
+
from langchain_core.documents import Document
|
|
11
|
+
from langchain_core.retrievers import BaseRetriever
|
|
12
|
+
from pydantic import ConfigDict, PrivateAttr, model_validator
|
|
13
|
+
|
|
14
|
+
from ceramic_ai import AsyncCeramic, Ceramic
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CeramicRetriever(BaseRetriever):
|
|
18
|
+
"""Retriever that uses Ceramic's web search API.
|
|
19
|
+
|
|
20
|
+
Setup:
|
|
21
|
+
Install the package and set your API key:
|
|
22
|
+
|
|
23
|
+
.. code-block:: bash
|
|
24
|
+
|
|
25
|
+
pip install langchain-ceramic
|
|
26
|
+
export CERAMIC_API_KEY="your-api-key"
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
.. code-block:: python
|
|
30
|
+
|
|
31
|
+
from langchain_ceramic import CeramicRetriever
|
|
32
|
+
|
|
33
|
+
retriever = CeramicRetriever(k=5)
|
|
34
|
+
docs = retriever.invoke("latest AI chip export restrictions")
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
38
|
+
|
|
39
|
+
api_key: Optional[str] = None
|
|
40
|
+
k: int = 10
|
|
41
|
+
|
|
42
|
+
_client: Ceramic = PrivateAttr(default=None)
|
|
43
|
+
_async_client: AsyncCeramic = PrivateAttr(default=None)
|
|
44
|
+
|
|
45
|
+
@model_validator(mode="after")
|
|
46
|
+
def validate_api_key(self) -> "CeramicRetriever":
|
|
47
|
+
key = self.api_key or os.environ.get("CERAMIC_API_KEY")
|
|
48
|
+
if not key:
|
|
49
|
+
raise ValueError(
|
|
50
|
+
"Ceramic API key required. Pass api_key= or set CERAMIC_API_KEY."
|
|
51
|
+
)
|
|
52
|
+
self._client = Ceramic(api_key=key)
|
|
53
|
+
self._async_client = AsyncCeramic(api_key=key)
|
|
54
|
+
return self
|
|
55
|
+
|
|
56
|
+
def _get_relevant_documents(
|
|
57
|
+
self, query: str, *, run_manager: CallbackManagerForRetrieverRun
|
|
58
|
+
) -> list[Document]:
|
|
59
|
+
response = self._client.search(query=query)
|
|
60
|
+
return [
|
|
61
|
+
Document(
|
|
62
|
+
page_content=result.description or "",
|
|
63
|
+
metadata={"title": result.title, "url": result.url},
|
|
64
|
+
)
|
|
65
|
+
for result in response.result.results[: self.k]
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
async def _aget_relevant_documents(
|
|
69
|
+
self, query: str, *, run_manager: AsyncCallbackManagerForRetrieverRun
|
|
70
|
+
) -> list[Document]:
|
|
71
|
+
response = await self._async_client.search(query=query)
|
|
72
|
+
return [
|
|
73
|
+
Document(
|
|
74
|
+
page_content=result.description or "",
|
|
75
|
+
metadata={"title": result.title, "url": result.url},
|
|
76
|
+
)
|
|
77
|
+
for result in response.result.results[: self.k]
|
|
78
|
+
]
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from typing import Optional, Type
|
|
5
|
+
|
|
6
|
+
from langchain_core.tools import BaseTool
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, model_validator
|
|
8
|
+
|
|
9
|
+
from ceramic_ai import AsyncCeramic, Ceramic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CeramicSearchInput(BaseModel):
|
|
13
|
+
query: str = Field(description="Search query to look up on the web.")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CeramicSearch(BaseTool):
|
|
17
|
+
"""Tool that queries the Ceramic web search API.
|
|
18
|
+
|
|
19
|
+
Setup:
|
|
20
|
+
.. code-block:: bash
|
|
21
|
+
|
|
22
|
+
pip install langchain-ceramic
|
|
23
|
+
export CERAMIC_API_KEY="your-api-key"
|
|
24
|
+
|
|
25
|
+
Example:
|
|
26
|
+
.. code-block:: python
|
|
27
|
+
|
|
28
|
+
from langchain_ceramic import CeramicSearch
|
|
29
|
+
|
|
30
|
+
tool = CeramicSearch(max_results=5)
|
|
31
|
+
tool.invoke("latest developments in GLP-1 drugs")
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
35
|
+
|
|
36
|
+
name: str = "ceramic_search"
|
|
37
|
+
description: str = (
|
|
38
|
+
"A web search tool powered by Ceramic. "
|
|
39
|
+
"Use this to find current information from the web. "
|
|
40
|
+
"Input should be a search query string."
|
|
41
|
+
)
|
|
42
|
+
args_schema: Type[BaseModel] = CeramicSearchInput
|
|
43
|
+
|
|
44
|
+
api_key: Optional[str] = None
|
|
45
|
+
max_results: int = 5
|
|
46
|
+
|
|
47
|
+
_client: Ceramic = PrivateAttr(default=None)
|
|
48
|
+
_async_client: AsyncCeramic = PrivateAttr(default=None)
|
|
49
|
+
|
|
50
|
+
@model_validator(mode="after")
|
|
51
|
+
def validate_api_key(self) -> "CeramicSearch":
|
|
52
|
+
key = self.api_key or os.environ.get("CERAMIC_API_KEY")
|
|
53
|
+
if not key:
|
|
54
|
+
raise ValueError(
|
|
55
|
+
"Ceramic API key required. Pass api_key= or set CERAMIC_API_KEY."
|
|
56
|
+
)
|
|
57
|
+
self._client = Ceramic(api_key=key)
|
|
58
|
+
self._async_client = AsyncCeramic(api_key=key)
|
|
59
|
+
return self
|
|
60
|
+
|
|
61
|
+
def _run(self, query: str) -> str:
|
|
62
|
+
response = self._client.search(query=query)
|
|
63
|
+
results = response.result.results[: self.max_results]
|
|
64
|
+
return "\n\n".join(
|
|
65
|
+
f"**{r.title}**\n{r.description}\nSource: {r.url}" for r in results
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
async def _arun(self, query: str) -> str:
|
|
69
|
+
response = await self._async_client.search(query=query)
|
|
70
|
+
results = response.result.results[: self.max_results]
|
|
71
|
+
return "\n\n".join(
|
|
72
|
+
f"**{r.title}**\n{r.description}\nSource: {r.url}" for r in results
|
|
73
|
+
)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "langchain-ceramic"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "An integration package connecting Ceramic and LangChain"
|
|
5
|
+
authors = ["Ceramic Team <info@ceramic.ai>"]
|
|
6
|
+
readme = "README.md"
|
|
7
|
+
repository = "https://github.com/CeramicTeam/langchain-ceramic"
|
|
8
|
+
license = "MIT"
|
|
9
|
+
include = ["langchain_ceramic/py.typed"]
|
|
10
|
+
|
|
11
|
+
[tool.poetry.dependencies]
|
|
12
|
+
python = ">=3.10,<4.0"
|
|
13
|
+
langchain-core = ">=0.3.0,<1.0.0"
|
|
14
|
+
ceramic-ai = ">=0.1.0"
|
|
15
|
+
|
|
16
|
+
[tool.poetry.group.dev.dependencies]
|
|
17
|
+
pytest = "^7.4.0"
|
|
18
|
+
pytest-asyncio = "^0.21.0"
|
|
19
|
+
langchain = ">=0.3.0"
|
|
20
|
+
|
|
21
|
+
[tool.pytest.ini_options]
|
|
22
|
+
addopts = "--strict-markers --strict-config --durations=5"
|
|
23
|
+
asyncio_mode = "auto"
|
|
24
|
+
markers = [
|
|
25
|
+
"integration: marks tests as integration tests (require CERAMIC_API_KEY)",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[tool.ruff.lint]
|
|
29
|
+
select = ["E", "F", "I"]
|
|
30
|
+
|
|
31
|
+
[build-system]
|
|
32
|
+
requires = ["poetry-core"]
|
|
33
|
+
build-backend = "poetry.core.masonry.api"
|