Skip to content

Commit a6d6c54

Browse files
authored
Merge pull request #45 from charlesLoder/update-deps
Update dependencies and reconfigure dev setup
2 parents 4fceb36 + b38c996 commit a6d6c54

8 files changed

Lines changed: 544 additions & 2309 deletions

File tree

dev/index.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
/// <reference types="vite/client" />
2-
import { Calculator } from "@langchain/community/tools/calculator";
3-
import { WikipediaQueryRun } from "@langchain/community/tools/wikipedia_query_run";
42
import Viewer from "@samvera/clover-iiif/viewer";
53
import { StrictMode } from "react";
64
import { createRoot } from "react-dom/client";
75
import { PluginControl, PluginPanel } from "../src/plugin";
86
import { UserTokenProvider } from "../src/providers";
7+
import { WikipediaQueryRun } from "./tools/wikipedia-query-run";
98

109
const wiki_tool = new WikipediaQueryRun({
1110
topKResults: 3,
1211
maxDocContentLength: 4000,
1312
});
1413

15-
const calc_tool = new Calculator();
16-
1714
createRoot(document.getElementById("root")!).render(
1815
<StrictMode>
1916
<Viewer
@@ -35,7 +32,7 @@ createRoot(document.getElementById("root")!).render(
3532
en: ["AI Chat"],
3633
},
3734
componentProps: {
38-
provider: new UserTokenProvider({ tools: [wiki_tool, calc_tool] }),
35+
provider: new UserTokenProvider({ tools: [wiki_tool] }),
3936
},
4037
},
4138
},

dev/tools/wikipedia-query-run.ts

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
/*
2+
* Adapted from @langchain/community (MIT License)
3+
* Source: https://github.com/langchain-ai/langchainjs/blob/5d8b75f2ad32ac8b322e5d03b99ff2ee99515e81/libs/langchain-community/src/tools/wikipedia_query_run.ts
4+
* Modifications: Removed build process causing rolldown errors in client; adjusted for browser-only usage; added origin=* to fetch requests
5+
* The original project license text is available in the root LICENSE file or at:
6+
* https://github.com/langchain-ai/langchainjs/blob/main/LICENSE
7+
*/
8+
9+
import { Tool } from "@langchain/core/tools";
10+
11+
/**
12+
* Interface for the parameters that can be passed to the
13+
* WikipediaQueryRun constructor.
14+
*/
15+
export interface WikipediaQueryRunParams {
16+
topKResults?: number;
17+
maxDocContentLength?: number;
18+
baseUrl?: string;
19+
}
20+
21+
/**
22+
* Type alias for URL parameters. Represents a record where keys are
23+
* strings and values can be string, number, boolean, undefined, or null.
24+
*/
25+
type UrlParameters = Record<string, string | number | boolean | undefined | null>;
26+
27+
/**
28+
* Interface for the structure of search results returned by the Wikipedia
29+
* API.
30+
*/
31+
interface SearchResults {
32+
query: {
33+
search: Array<{
34+
title: string;
35+
}>;
36+
};
37+
}
38+
39+
/**
40+
* Interface for the structure of a page returned by the Wikipedia API.
41+
*/
42+
interface Page {
43+
pageid: number;
44+
ns: number;
45+
title: string;
46+
extract: string;
47+
}
48+
49+
/**
50+
* Interface for the structure of a page result returned by the Wikipedia
51+
* API.
52+
*/
53+
interface PageResult {
54+
batchcomplete: string;
55+
query: {
56+
pages: Record<string, Page>;
57+
};
58+
}
59+
60+
/**
61+
* Wikipedia query tool integration.
62+
*
63+
* Setup:
64+
* Install `@langchain/community`. You'll also need an API key.
65+
*
66+
* ```bash
67+
* npm install @langchain/community
68+
* ```
69+
*
70+
* ## [Constructor args](https://api.js.langchain.com/classes/_langchain_community.tools_wikipedia_query_run.WikipediaQueryRun.html#constructor)
71+
*
72+
* <details open>
73+
* <summary><strong>Instantiate</strong></summary>
74+
*
75+
* ```typescript
76+
* import { WikipediaQueryRun } from "@langchain/community/tools/wikipedia_query_run";
77+
*
78+
* const tool = new WikipediaQueryRun({
79+
* topKResults: 3,
80+
* maxDocContentLength: 4000,
81+
* });
82+
* ```
83+
* </details>
84+
*
85+
* <br />
86+
*
87+
* <details>
88+
*
89+
* <summary><strong>Invocation</strong></summary>
90+
*
91+
* ```typescript
92+
* await tool.invoke("what is the current weather in sf?");
93+
* ```
94+
* </details>
95+
*
96+
* <br />
97+
*
98+
* <details>
99+
*
100+
* <summary><strong>Invocation with tool call</strong></summary>
101+
*
102+
* ```typescript
103+
* // This is usually generated by a model, but we'll create a tool call directly for demo purposes.
104+
* const modelGeneratedToolCall = {
105+
* args: {
106+
* input: "what is the current weather in sf?",
107+
* },
108+
* id: "tool_call_id",
109+
* name: tool.name,
110+
* type: "tool_call",
111+
* };
112+
* await tool.invoke(modelGeneratedToolCall);
113+
* ```
114+
*
115+
* ```text
116+
* ToolMessage {
117+
* "content": "...",
118+
* "name": "wikipedia-api",
119+
* "additional_kwargs": {},
120+
* "response_metadata": {},
121+
* "tool_call_id": "tool_call_id"
122+
* }
123+
* ```
124+
* </details>
125+
*/
126+
export class WikipediaQueryRun extends Tool {
127+
static lc_name() {
128+
return "WikipediaQueryRun";
129+
}
130+
131+
name = "wikipedia-api";
132+
133+
description = "A tool for interacting with and fetching data from the Wikipedia API.";
134+
135+
protected topKResults = 3;
136+
137+
protected maxDocContentLength = 4000;
138+
139+
protected baseUrl = "https://en.wikipedia.org/w/api.php";
140+
141+
constructor(params: WikipediaQueryRunParams = {}) {
142+
super();
143+
144+
this.topKResults = params.topKResults ?? this.topKResults;
145+
this.maxDocContentLength = params.maxDocContentLength ?? this.maxDocContentLength;
146+
this.baseUrl = params.baseUrl ?? this.baseUrl;
147+
}
148+
149+
async _call(query: string): Promise<string> {
150+
const searchResults = await this._fetchSearchResults(query);
151+
const summaries: string[] = [];
152+
153+
for (let i = 0; i < Math.min(this.topKResults, searchResults.query.search.length); i += 1) {
154+
const page = searchResults.query.search[i].title;
155+
const pageDetails = await this._fetchPage(page, true);
156+
157+
if (pageDetails) {
158+
const summary = `Page: ${page}\nSummary: ${pageDetails.extract}`;
159+
summaries.push(summary);
160+
}
161+
}
162+
163+
if (summaries.length === 0) {
164+
return "No good Wikipedia Search Result was found";
165+
} else {
166+
return summaries.join("\n\n").slice(0, this.maxDocContentLength);
167+
}
168+
}
169+
170+
/**
171+
* Fetches the content of a specific Wikipedia page. It returns the
172+
* extracted content as a string.
173+
* @param page The specific Wikipedia page to fetch its content.
174+
* @param redirect A boolean value to indicate whether to redirect or not.
175+
* @returns The extracted content of the specific Wikipedia page as a string.
176+
*/
177+
public async content(page: string, redirect = true): Promise<string> {
178+
try {
179+
const result = await this._fetchPage(page, redirect);
180+
return result.extract;
181+
} catch (error) {
182+
throw new Error(`Failed to fetch content for page "${page}": ${error}`);
183+
}
184+
}
185+
186+
/**
187+
* Builds a URL for the Wikipedia API using the provided parameters.
188+
* @param parameters The parameters to be used in building the URL.
189+
* @returns A string representing the built URL.
190+
*/
191+
protected buildUrl<P extends UrlParameters>(parameters: P): string {
192+
const nonUndefinedParams: [string, string][] = Object.entries(parameters)
193+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
194+
.filter(([_, value]) => value !== undefined)
195+
.map(([key, value]) => [key, `${value}`]);
196+
const searchParams = new URLSearchParams(nonUndefinedParams);
197+
return `${this.baseUrl}?${searchParams}`;
198+
}
199+
200+
private async _fetchSearchResults(query: string): Promise<SearchResults> {
201+
const searchParams = new URLSearchParams({
202+
action: "query",
203+
list: "search",
204+
srsearch: query,
205+
origin: "*",
206+
format: "json",
207+
});
208+
209+
const response = await fetch(`${this.baseUrl}?${searchParams.toString()}`);
210+
if (!response.ok) throw new Error("Network response was not ok");
211+
212+
const data: SearchResults = await response.json();
213+
214+
return data;
215+
}
216+
217+
private async _fetchPage(page: string, redirect: boolean): Promise<Page> {
218+
const params = new URLSearchParams({
219+
action: "query",
220+
prop: "extracts",
221+
explaintext: "true",
222+
redirects: redirect ? "1" : "0",
223+
format: "json",
224+
origin: "*",
225+
titles: page,
226+
});
227+
228+
const response = await fetch(`${this.baseUrl}?${params.toString()}`);
229+
if (!response.ok) throw new Error("Network response was not ok");
230+
231+
const data: PageResult = await response.json();
232+
const { pages } = data.query;
233+
const pageId = Object.keys(pages)[0];
234+
235+
return pages[pageId];
236+
}
237+
}

dev/vite.config.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { defineConfig, mergeConfig } from "vite";
2+
import config from "../vite.config.ts";
3+
4+
export default mergeConfig(
5+
config,
6+
defineConfig({
7+
root: "dev",
8+
server: {
9+
port: 3000,
10+
},
11+
}),
12+
);

0 commit comments

Comments
 (0)