langchain-serpex-python 0.1.0__py3-none-any.whl
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_serpex_python/__init__.py +10 -0
- langchain_serpex_python/py.typed +1 -0
- langchain_serpex_python/tools.py +285 -0
- langchain_serpex_python-0.1.0.dist-info/METADATA +187 -0
- langchain_serpex_python-0.1.0.dist-info/RECORD +7 -0
- langchain_serpex_python-0.1.0.dist-info/WHEEL +4 -0
- langchain_serpex_python-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""SERPEX integration for LangChain.
|
|
2
|
+
|
|
3
|
+
This module provides tools for searching the web using the SERPEX API,
|
|
4
|
+
which supports multiple search engines including Google, Bing, DuckDuckGo,
|
|
5
|
+
Baidu, and Yandex.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from langchain_serpex_python.tools import SerpexSearchResults
|
|
9
|
+
|
|
10
|
+
__all__ = ["SerpexSearchResults"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Marker file for PEP 561
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"""SERPEX Search Tool for LangChain."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import httpx
|
|
9
|
+
from langchain_core.callbacks import CallbackManagerForToolRun
|
|
10
|
+
from langchain_core.tools import BaseTool
|
|
11
|
+
from pydantic import Field, SecretStr, model_validator
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SerpexSearchResults(BaseTool):
|
|
15
|
+
"""Tool for searching the web using the SERPEX API.
|
|
16
|
+
|
|
17
|
+
SERPEX provides multi-engine search results from Google, Bing, DuckDuckGo,
|
|
18
|
+
Brave, Yahoo, and Yandex search engines in JSON format.
|
|
19
|
+
|
|
20
|
+
Setup:
|
|
21
|
+
Install `langchain-serpex` and set environment variable `SERPEX_API_KEY`.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install -U langchain-serpex
|
|
25
|
+
export SERPEX_API_KEY="your-serpex-api-key"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Instantiation:
|
|
29
|
+
```python
|
|
30
|
+
from langchain_serpex import SerpexSearchResults
|
|
31
|
+
|
|
32
|
+
# With explicit API key
|
|
33
|
+
tool = SerpexSearchResults(
|
|
34
|
+
api_key="your-serpex-api-key",
|
|
35
|
+
engine="auto", # or google, bing, duckduckgo, brave, yahoo, yandex
|
|
36
|
+
time_range="day" # optional: all, day, week, month, year
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Or using environment variable
|
|
40
|
+
tool = SerpexSearchResults()
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Invocation:
|
|
44
|
+
```python
|
|
45
|
+
# Basic search
|
|
46
|
+
results = tool.invoke("latest AI developments")
|
|
47
|
+
print(results)
|
|
48
|
+
|
|
49
|
+
# With specific parameters
|
|
50
|
+
results = tool.invoke({
|
|
51
|
+
"query": "Python programming",
|
|
52
|
+
"engine": "google",
|
|
53
|
+
"time_range": "week"
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Example with Agent:
|
|
58
|
+
```python
|
|
59
|
+
from langchain_serpex import SerpexSearchResults
|
|
60
|
+
from langchain_openai import ChatOpenAI
|
|
61
|
+
from langchain.agents import initialize_agent, AgentType
|
|
62
|
+
|
|
63
|
+
search = SerpexSearchResults(api_key="your-key")
|
|
64
|
+
llm = ChatOpenAI(temperature=0)
|
|
65
|
+
|
|
66
|
+
agent = initialize_agent(
|
|
67
|
+
tools=[search],
|
|
68
|
+
llm=llm,
|
|
69
|
+
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
result = agent.run("What's the latest news about AI?")
|
|
73
|
+
```
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
name: str = "serpex_search"
|
|
77
|
+
description: str = (
|
|
78
|
+
"A powerful multi-engine web search tool. "
|
|
79
|
+
"Useful for answering questions about current events, "
|
|
80
|
+
"finding information from the web, and getting real-time data. "
|
|
81
|
+
"Input should be a search query string. "
|
|
82
|
+
"Supports automatic routing with retry logic and multiple search engines "
|
|
83
|
+
"(Google, Bing, DuckDuckGo, Brave, Yahoo, Yandex)."
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
api_key: SecretStr = Field(default_factory=lambda: SecretStr(""))
|
|
87
|
+
engine: str = Field(
|
|
88
|
+
default="auto",
|
|
89
|
+
description=(
|
|
90
|
+
"Search engine: auto, google, bing, duckduckgo, brave, yahoo, yandex"
|
|
91
|
+
),
|
|
92
|
+
)
|
|
93
|
+
category: str = Field(
|
|
94
|
+
default="web",
|
|
95
|
+
description="Search category (currently only 'web' supported)",
|
|
96
|
+
)
|
|
97
|
+
time_range: str | None = Field(
|
|
98
|
+
default=None,
|
|
99
|
+
description=(
|
|
100
|
+
"Time range: all, day, week, month, year (not supported by Brave)"
|
|
101
|
+
),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
base_url: str = Field(default="https://api.serpex.dev")
|
|
105
|
+
|
|
106
|
+
@model_validator(mode="before")
|
|
107
|
+
@classmethod
|
|
108
|
+
def validate_environment(cls, values: dict[str, Any]) -> dict[str, Any]:
|
|
109
|
+
"""Validate that API key exists in environment."""
|
|
110
|
+
api_key = values.get("api_key")
|
|
111
|
+
if not api_key or (
|
|
112
|
+
isinstance(api_key, SecretStr) and not api_key.get_secret_value()
|
|
113
|
+
):
|
|
114
|
+
api_key_from_env = os.getenv("SERPEX_API_KEY", "")
|
|
115
|
+
if api_key_from_env:
|
|
116
|
+
values["api_key"] = SecretStr(api_key_from_env)
|
|
117
|
+
elif isinstance(api_key, str):
|
|
118
|
+
values["api_key"] = SecretStr(api_key)
|
|
119
|
+
|
|
120
|
+
return values
|
|
121
|
+
|
|
122
|
+
def _build_params(self, query: str, **kwargs: Any) -> dict[str, Any]:
|
|
123
|
+
"""Build parameters for the API request."""
|
|
124
|
+
params: dict[str, Any] = {
|
|
125
|
+
"q": query,
|
|
126
|
+
"engine": kwargs.get("engine", self.engine),
|
|
127
|
+
"category": kwargs.get("category", self.category),
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
# Add time_range if specified
|
|
131
|
+
time_range = kwargs.get("time_range") or self.time_range
|
|
132
|
+
if time_range is not None:
|
|
133
|
+
params["time_range"] = time_range
|
|
134
|
+
|
|
135
|
+
return params
|
|
136
|
+
|
|
137
|
+
def _format_results(self, data: dict[str, Any]) -> str:
|
|
138
|
+
"""Format the search results into a readable string."""
|
|
139
|
+
results_parts: list[str] = []
|
|
140
|
+
|
|
141
|
+
# Instant answers (from knowledge panels/answer boxes)
|
|
142
|
+
if (
|
|
143
|
+
"answers" in data
|
|
144
|
+
and isinstance(data["answers"], list)
|
|
145
|
+
and len(data["answers"]) > 0
|
|
146
|
+
):
|
|
147
|
+
answer = data["answers"][0]
|
|
148
|
+
if "answer" in answer and answer["answer"]:
|
|
149
|
+
results_parts.append(f"Answer: {answer['answer']}")
|
|
150
|
+
elif "snippet" in answer and answer["snippet"]:
|
|
151
|
+
results_parts.append(f"Featured Snippet: {answer['snippet']}")
|
|
152
|
+
|
|
153
|
+
# Infoboxes (knowledge panels)
|
|
154
|
+
if (
|
|
155
|
+
"infoboxes" in data
|
|
156
|
+
and isinstance(data["infoboxes"], list)
|
|
157
|
+
and len(data["infoboxes"]) > 0
|
|
158
|
+
):
|
|
159
|
+
infobox = data["infoboxes"][0]
|
|
160
|
+
if "description" in infobox and infobox["description"]:
|
|
161
|
+
results_parts.append(f"Knowledge Panel: {infobox['description']}")
|
|
162
|
+
|
|
163
|
+
# Organic search results
|
|
164
|
+
if (
|
|
165
|
+
"results" in data
|
|
166
|
+
and isinstance(data["results"], list)
|
|
167
|
+
and len(data["results"]) > 0
|
|
168
|
+
):
|
|
169
|
+
num_results = data.get("metadata", {}).get(
|
|
170
|
+
"number_of_results", len(data["results"])
|
|
171
|
+
)
|
|
172
|
+
results_parts.append(f"\nFound {num_results} results:\n")
|
|
173
|
+
|
|
174
|
+
for i, result in enumerate(data["results"][:10], 1):
|
|
175
|
+
title = result.get("title", "")
|
|
176
|
+
url = result.get("url", "")
|
|
177
|
+
snippet = result.get("snippet", "")
|
|
178
|
+
published_date = result.get("published_date")
|
|
179
|
+
|
|
180
|
+
result_text = f"[{i}] {title}"
|
|
181
|
+
if url:
|
|
182
|
+
result_text += f"\nURL: {url}"
|
|
183
|
+
if snippet:
|
|
184
|
+
result_text += f"\n{snippet}"
|
|
185
|
+
if published_date:
|
|
186
|
+
result_text += f"\nPublished: {published_date}"
|
|
187
|
+
|
|
188
|
+
results_parts.append(result_text)
|
|
189
|
+
|
|
190
|
+
# Search suggestions
|
|
191
|
+
if (
|
|
192
|
+
not results_parts
|
|
193
|
+
and "suggestions" in data
|
|
194
|
+
and isinstance(data["suggestions"], list)
|
|
195
|
+
and len(data["suggestions"]) > 0
|
|
196
|
+
):
|
|
197
|
+
results_parts.append("No direct results found. Related searches:")
|
|
198
|
+
results_parts.extend(data["suggestions"])
|
|
199
|
+
|
|
200
|
+
# Query corrections
|
|
201
|
+
if (
|
|
202
|
+
not results_parts
|
|
203
|
+
and "corrections" in data
|
|
204
|
+
and isinstance(data["corrections"], list)
|
|
205
|
+
and len(data["corrections"]) > 0
|
|
206
|
+
):
|
|
207
|
+
results_parts.append(f"Did you mean: {', '.join(data['corrections'])}?")
|
|
208
|
+
|
|
209
|
+
if not results_parts:
|
|
210
|
+
return "No search results found."
|
|
211
|
+
|
|
212
|
+
return "\n\n".join(results_parts)
|
|
213
|
+
|
|
214
|
+
def _run(
|
|
215
|
+
self,
|
|
216
|
+
query: str,
|
|
217
|
+
run_manager: CallbackManagerForToolRun | None = None,
|
|
218
|
+
**kwargs: Any,
|
|
219
|
+
) -> str:
|
|
220
|
+
"""Execute the search."""
|
|
221
|
+
params = self._build_params(query, **kwargs)
|
|
222
|
+
|
|
223
|
+
headers = {
|
|
224
|
+
"Authorization": f"Bearer {self.api_key.get_secret_value()}",
|
|
225
|
+
"Content-Type": "application/json",
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
url = f"{self.base_url}/api/search"
|
|
229
|
+
|
|
230
|
+
try:
|
|
231
|
+
with httpx.Client() as client:
|
|
232
|
+
response = client.get(url, params=params, headers=headers, timeout=30.0)
|
|
233
|
+
response.raise_for_status()
|
|
234
|
+
data = response.json()
|
|
235
|
+
|
|
236
|
+
if "error" in data:
|
|
237
|
+
return f"SERPEX API error: {data['error']}"
|
|
238
|
+
|
|
239
|
+
return self._format_results(data)
|
|
240
|
+
|
|
241
|
+
except httpx.HTTPStatusError as e:
|
|
242
|
+
return f"HTTP error occurred: {e.response.status_code} - {e.response.text}"
|
|
243
|
+
except httpx.RequestError as e:
|
|
244
|
+
return f"Request error occurred: {str(e)}"
|
|
245
|
+
except Exception as e:
|
|
246
|
+
return f"Error searching with SERPEX: {str(e)}"
|
|
247
|
+
|
|
248
|
+
async def _arun(
|
|
249
|
+
self,
|
|
250
|
+
query: str,
|
|
251
|
+
run_manager: CallbackManagerForToolRun | None = None,
|
|
252
|
+
**kwargs: Any,
|
|
253
|
+
) -> str:
|
|
254
|
+
"""Execute the search asynchronously."""
|
|
255
|
+
params = self._build_params(query, **kwargs)
|
|
256
|
+
|
|
257
|
+
headers = {
|
|
258
|
+
"Authorization": f"Bearer {self.api_key.get_secret_value()}",
|
|
259
|
+
"Content-Type": "application/json",
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
url = f"{self.base_url}/api/search"
|
|
263
|
+
|
|
264
|
+
try:
|
|
265
|
+
async with httpx.AsyncClient() as client:
|
|
266
|
+
response = await client.get(
|
|
267
|
+
url, params=params, headers=headers, timeout=30.0
|
|
268
|
+
)
|
|
269
|
+
response.raise_for_status()
|
|
270
|
+
data = response.json()
|
|
271
|
+
|
|
272
|
+
if "error" in data:
|
|
273
|
+
return f"SERPEX API error: {data['error']}"
|
|
274
|
+
|
|
275
|
+
return self._format_results(data)
|
|
276
|
+
|
|
277
|
+
except httpx.HTTPStatusError as e:
|
|
278
|
+
return f"HTTP error occurred: {e.response.status_code} - {e.response.text}"
|
|
279
|
+
except httpx.RequestError as e:
|
|
280
|
+
return f"Request error occurred: {str(e)}"
|
|
281
|
+
except Exception as e:
|
|
282
|
+
return f"Error searching with SERPEX: {str(e)}"
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
__all__ = ["SerpexSearchResults"]
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: langchain-serpex-python
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: An integration package connecting SERPEX and LangChain (Python)
|
|
5
|
+
Project-URL: Homepage, https://docs.langchain.com/oss/python/integrations/providers/serpex
|
|
6
|
+
Project-URL: Documentation, https://serpex.dev/docs
|
|
7
|
+
Project-URL: Source, https://github.com/divyeshradadiya/langchain-serpex
|
|
8
|
+
Project-URL: Repository, https://github.com/divyeshradadiya/langchain-serpex
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Python: <4.0.0,>=3.10.0
|
|
12
|
+
Requires-Dist: httpx>=0.27.0
|
|
13
|
+
Requires-Dist: langchain-core<2.0.0,>=1.0.0
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# langchain-serpex-python
|
|
17
|
+
|
|
18
|
+
[](https://pypi.org/project/langchain-serpex-python/#history)
|
|
19
|
+
[](https://opensource.org/licenses/MIT)
|
|
20
|
+
[](https://twitter.com/langchainai)
|
|
21
|
+
|
|
22
|
+
This package contains the LangChain integration with SERPEX (Python).
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install langchain-serpex-python
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## What is SERPEX?
|
|
31
|
+
|
|
32
|
+
SERPEX is a powerful multi-engine search API that provides access to search results from Google, Bing, DuckDuckGo, Baidu, Yandex, and other search engines in JSON format. It's designed for developers building AI applications, SEO tools, market research platforms, and data aggregation services.
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
- **Multi-Engine Support**: Search across Google, Bing, DuckDuckGo, Baidu, and Yandex
|
|
37
|
+
- **Rich Results**: Get organic results, answer boxes, knowledge graphs, news, images, videos, and shopping results
|
|
38
|
+
- **Localization**: Support for location-based and language-specific searches
|
|
39
|
+
- **Real-time Data**: Access to current search results
|
|
40
|
+
- **Easy Integration**: Simple API with comprehensive documentation
|
|
41
|
+
|
|
42
|
+
## Quick Start
|
|
43
|
+
|
|
44
|
+
### Get Your API Key
|
|
45
|
+
|
|
46
|
+
Sign up at [SERPEX](https://serpex.dev) to get your API key.
|
|
47
|
+
|
|
48
|
+
### Basic Usage
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from langchain_serpex_python import SerpexSearchResults
|
|
52
|
+
|
|
53
|
+
# Initialize the tool
|
|
54
|
+
tool = SerpexSearchResults(
|
|
55
|
+
api_key="your-serpex-api-key",
|
|
56
|
+
engine="google",
|
|
57
|
+
num_results=10
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Perform a search
|
|
61
|
+
results = tool.invoke("latest AI developments")
|
|
62
|
+
print(results)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### With Agents
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from langchain_serpex_python import SerpexSearchResults
|
|
69
|
+
from langchain_openai import ChatOpenAI
|
|
70
|
+
from langchain.agents import initialize_agent, AgentType
|
|
71
|
+
|
|
72
|
+
# Initialize the search tool
|
|
73
|
+
search_tool = SerpexSearchResults(
|
|
74
|
+
api_key="your-serpex-api-key",
|
|
75
|
+
engine="google",
|
|
76
|
+
num_results=5
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Initialize the LLM
|
|
80
|
+
llm = ChatOpenAI(temperature=0)
|
|
81
|
+
|
|
82
|
+
# Create an agent with the search tool
|
|
83
|
+
agent = initialize_agent(
|
|
84
|
+
tools=[search_tool],
|
|
85
|
+
llm=llm,
|
|
86
|
+
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
|
|
87
|
+
verbose=True
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Run the agent
|
|
91
|
+
result = agent.run("What are the latest developments in quantum computing?")
|
|
92
|
+
print(result)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Advanced Configuration
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from langchain_serpex_python import SerpexSearchResults
|
|
99
|
+
|
|
100
|
+
# Configure with advanced parameters
|
|
101
|
+
tool = SerpexSearchResults(
|
|
102
|
+
api_key="your-serpex-api-key",
|
|
103
|
+
engine="google",
|
|
104
|
+
num_results=20,
|
|
105
|
+
gl="us", # Country code
|
|
106
|
+
hl="en", # Language code
|
|
107
|
+
location="New York", # Specific location
|
|
108
|
+
time_period="m", # Results from past month
|
|
109
|
+
safe_search="moderate"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Search for location-specific results
|
|
113
|
+
results = tool.invoke("best restaurants")
|
|
114
|
+
print(results)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Different Search Engines
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from langchain_serpex_python import SerpexSearchResults
|
|
121
|
+
|
|
122
|
+
# Google Search
|
|
123
|
+
google_tool = SerpexSearchResults(api_key="your-key", engine="google")
|
|
124
|
+
google_results = google_tool.invoke("Python programming")
|
|
125
|
+
|
|
126
|
+
# Bing Search
|
|
127
|
+
bing_tool = SerpexSearchResults(api_key="your-key", engine="bing")
|
|
128
|
+
bing_results = bing_tool.invoke("Python programming")
|
|
129
|
+
|
|
130
|
+
# DuckDuckGo Search
|
|
131
|
+
ddg_tool = SerpexSearchResults(api_key="your-key", engine="duckduckgo")
|
|
132
|
+
ddg_results = ddg_tool.invoke("Python programming")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Configuration
|
|
136
|
+
|
|
137
|
+
### Environment Variables
|
|
138
|
+
|
|
139
|
+
You can set your SERPEX API key as an environment variable:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
export SERPEX_API_KEY="your-serpex-api-key"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Then use the tool without passing the API key:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from langchain_serpex_python import SerpexSearchResults
|
|
149
|
+
|
|
150
|
+
tool = SerpexSearchResults() # Will use SERPEX_API_KEY from environment
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Parameters
|
|
154
|
+
|
|
155
|
+
- `api_key` (str): Your SERPEX API key (required)
|
|
156
|
+
- `engine` (str): Search engine to use - "google", "bing", "duckduckgo", "baidu", "yandex" (default: "google")
|
|
157
|
+
- `num_results` (int): Number of results to return, 1-100 (default: 10)
|
|
158
|
+
- `gl` (str): Country code for localized results (e.g., "us", "uk", "ca")
|
|
159
|
+
- `hl` (str): Language code (e.g., "en", "es", "fr")
|
|
160
|
+
- `location` (str): Specific location for localized results
|
|
161
|
+
- `time_period` (str): Time filter - "d" (day), "w" (week), "m" (month), "y" (year)
|
|
162
|
+
- `safe_search` (str): Safe search filter - "off", "moderate", "strict"
|
|
163
|
+
|
|
164
|
+
## Documentation
|
|
165
|
+
|
|
166
|
+
For more detailed documentation, visit:
|
|
167
|
+
- [LangChain Documentation](https://python.langchain.com)
|
|
168
|
+
- [SERPEX API Documentation](https://serpex.dev/docs)
|
|
169
|
+
|
|
170
|
+
## Support
|
|
171
|
+
|
|
172
|
+
For issues and questions:
|
|
173
|
+
- GitHub Issues: [langchain-serpex issues](https://github.com/langchain-ai/langchain/issues)
|
|
174
|
+
- SERPEX Support: [support@serpex.dev](mailto:support@serpex.dev)
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
This package is licensed under the MIT License.
|
|
179
|
+
|
|
180
|
+
## CI / Publishing
|
|
181
|
+
|
|
182
|
+
A GitHub Actions workflow is provided to publish the package to PyPI when a tag like `v*` is pushed or when a release is published.
|
|
183
|
+
|
|
184
|
+
Required repository secret:
|
|
185
|
+
- `PYPI_API_TOKEN` — a PyPI API token with permission to upload the package. Set this in the repository's Settings → Secrets → Actions.
|
|
186
|
+
|
|
187
|
+
To publish a new release, create a tag `vMAJOR.MINOR.PATCH` and push it or create a release in GitHub; the workflow will build sdist and wheel and upload them to PyPI.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
langchain_serpex_python/__init__.py,sha256=owZSYVufiNrS44tCs9XlDkJdh3ZcW1cibAOxDbFqk0A,305
|
|
2
|
+
langchain_serpex_python/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26
|
|
3
|
+
langchain_serpex_python/tools.py,sha256=H45fTP0XvPBk_kkgGAcLDYclRQ96Z1V_oI36jc_knGU,9488
|
|
4
|
+
langchain_serpex_python-0.1.0.dist-info/METADATA,sha256=v_2LDkohScvgs7xrsAUi-sIcgLMsZbMVFvfitgsbzXA,5906
|
|
5
|
+
langchain_serpex_python-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
+
langchain_serpex_python-0.1.0.dist-info/licenses/LICENSE,sha256=oB3P_cEpG0BD8qgdJJqfPkXJA28jCMnN_u_hg3E3HoA,1066
|
|
7
|
+
langchain_serpex_python-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 LangChain
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|