Skip to content

Commit

Permalink
Merge pull request #39 from dcSpark/nico/update_cb_and_add_perp
Browse files Browse the repository at this point in the history
Add Perplexity
  • Loading branch information
nicarq authored Sep 7, 2024
2 parents 64354fd + d068bb2 commit 62961dd
Show file tree
Hide file tree
Showing 20 changed files with 365 additions and 3 deletions.
6 changes: 6 additions & 0 deletions apps/shinkai-tool-perplexity-api/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* eslint-disable */
export default {
displayName: '@shinkai_protocol/shinkai-tool-perplexity-api',
preset: '../../jest.preset.js',
coverageDirectory: '../../coverage/apps/shinkai-tool-perplexity-api'
};
4 changes: 4 additions & 0 deletions apps/shinkai-tool-perplexity-api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "@shinkai_protocol/shinkai-tool-perplexity-api",
"type": "commonjs"
}
30 changes: 30 additions & 0 deletions apps/shinkai-tool-perplexity-api/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@shinkai_protocol/shinkai-tool-perplexity-api",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/shinkai-tool-perplexity-api/src",
"projectType": "library",
"tags": ["tool"],
"targets": {
"build": {
"executor": "nx:run-commands",
"defaultConfiguration": "production",
"options": {
"command": "npx ts-node scripts/tool-bundler.ts --entry ./apps/shinkai-tool-perplexity-api/src/index.ts --outputFolder ./dist/apps/shinkai-tool-perplexity-api"
},
"configurations": {
"development": {},
"production": {}
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": [
"apps/shinkai-tool-perplexity-api/**/*.ts",
"apps/shinkai-tool-perplexity-api/package.json"
]
}
}
}
}
7 changes: 7 additions & 0 deletions apps/shinkai-tool-perplexity-api/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Tool } from '../src/index';

test('exists definition', () => {
const tool = new Tool({ apiKey: 'pplx-XXX' });
const definition = tool.getDefinition();
expect(definition).toBeInstanceOf(Object);
});
84 changes: 84 additions & 0 deletions apps/shinkai-tool-perplexity-api/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { BaseTool, RunResult } from '@shinkai_protocol/shinkai-tools-builder';
import { ToolDefinition } from 'libs/shinkai-tools-builder/src/tool-definition';
import TurndownService from 'turndown';
import axios from 'axios';

type Config = {
apiKey: string;
};
type Params = {
query: string;
};

type Result = {
response: string;
};

interface PerplexityResponse {
choices: Array<{
message: {
content: string;
};
}>;
}

export class Tool extends BaseTool<Config, Params, Result> {
definition: ToolDefinition<Config, Params, Result> = {
id: 'shinkai-tool-perplexity-api',
name: 'Shinkai: Perplexity API',
description: 'Searches the web using Perplexity API (limited)',
author: 'Shinkai',
keywords: ['perplexity', 'api', 'shinkai'],
configurations: {
type: 'object',
properties: {
apiKey: { type: 'string' },
},
required: ['apiKey'],
},
parameters: {
type: 'object',
properties: {
query: { type: 'string' },
},
required: ['query'],
},
result: {
type: 'object',
properties: {
response: { type: 'string' },
},
required: ['response'],
},
};

async run(params: Params): Promise<RunResult<Result>> {
const response = await fetch('https://api.perplexity.ai/chat/completions', {
method: 'POST',
headers: {
accept: 'application/json',
authorization: `Bearer ${this.config.apiKey}`,
'content-type': 'application/json',
},
body: JSON.stringify({
model: 'llama-3.1-sonar-small-128k-online',
messages: [
{ role: 'system', content: 'Be precise and concise.' },
{ role: 'user', content: params.query },
],
}),
});

if (!response.ok) {
throw new Error(
`Failed to fetch data from Perplexity API, status: ${response.status}`,
);
}

const data = (await response.json()) as PerplexityResponse;
const responseContent =
data.choices[0]?.message?.content || 'No information available';

return { data: { response: responseContent } };
}
}
4 changes: 4 additions & 0 deletions apps/shinkai-tool-perplexity-api/tsconfig.app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"include": ["./src/**/*.ts"]
}
5 changes: 5 additions & 0 deletions apps/shinkai-tool-perplexity-api/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {},
"include": ["./src/**/*.ts"]
}
14 changes: 14 additions & 0 deletions apps/shinkai-tool-perplexity-api/tsconfig.spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"jest.config.ts",
"test/**/*.test.ts",
"test/**/*.spec.ts",
"test/**/*.d.ts"
]
}
6 changes: 6 additions & 0 deletions apps/shinkai-tool-perplexity/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* eslint-disable */
export default {
displayName: '@shinkai_protocol/shinkai-tool-perplexity',
preset: '../../jest.preset.js',
coverageDirectory: '../../coverage/apps/shinkai-tool-perplexity',
};
4 changes: 4 additions & 0 deletions apps/shinkai-tool-perplexity/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "@shinkai_protocol/shinkai-tool-perplexity",
"type": "commonjs"
}
30 changes: 30 additions & 0 deletions apps/shinkai-tool-perplexity/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@shinkai_protocol/shinkai-tool-perplexity",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/shinkai-tool-perplexity/src",
"projectType": "library",
"tags": ["tool"],
"targets": {
"build": {
"executor": "nx:run-commands",
"defaultConfiguration": "production",
"options": {
"command": "npx ts-node scripts/tool-bundler.ts --entry ./apps/shinkai-tool-perplexity/src/index.ts --outputFolder ./dist/apps/shinkai-tool-perplexity"
},
"configurations": {
"development": {},
"production": {}
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": [
"apps/shinkai-tool-perplexity/**/*.ts",
"apps/shinkai-tool-perplexity/package.json"
]
}
}
}
}
3 changes: 3 additions & 0 deletions apps/shinkai-tool-perplexity/src/chrome-paths.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module 'chrome-paths' {
const chrome: string;
}
15 changes: 15 additions & 0 deletions apps/shinkai-tool-perplexity/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Tool } from '../src/index';

test('exists definition', async () => {
const tool = new Tool({});
const definition = tool.getDefinition();
expect(definition).toBeInstanceOf(Object);
});

test('run', async () => {
const tool = new Tool({
chromePath: process.env?.CHROME_PATH,
});
const run_result = await tool.run({ query: 'What is the meaning of life?' });
expect(run_result.data.response).toEqual(expect.any(String));
}, 15000);
107 changes: 107 additions & 0 deletions apps/shinkai-tool-perplexity/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { BaseTool, RunResult } from '@shinkai_protocol/shinkai-tools-builder';
import { ToolDefinition } from 'libs/shinkai-tools-builder/src/tool-definition';
import * as playwright from 'playwright';
import * as chromePaths from 'chrome-paths';
import TurndownService = require('turndown');

type Config = {
chromePath?: string;
};
type Params = {
query: string;
};
type Result = { response: string };

export class Tool extends BaseTool<Config, Params, Result> {
definition: ToolDefinition<Config, Params, Result> = {
id: 'shinkai-tool-perplexity',
name: 'Shinkai: Perplexity',
description: 'Searches the internet using Perplexity',
author: 'Shinkai',
keywords: ['perplexity', 'shinkai'],
configurations: {
type: 'object',
properties: {
chromePath: { type: 'string', nullable: true },
},
required: [],
},
parameters: {
type: 'object',
properties: {
query: { type: 'string' },
},
required: ['query'],
},
result: {
type: 'object',
properties: {
response: { type: 'string' },
},
required: ['response'],
},
};

async run(params: Params): Promise<RunResult<Result>> {
const browser = await playwright['chromium'].launch({
executablePath: this.config?.chromePath || chromePaths.chrome,
// headless: false,
});
const context = await browser.newContext({
viewport: { width: 1280, height: 800 }, // Set viewport size
userAgent:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36', // Set Mac user agent
});
const page = await context.newPage();

console.log("Navigating to Perplexity's website...");
await page.goto('https://www.perplexity.ai/');

console.log('Waiting for the page to load...');
await page.waitForTimeout(2500);

console.log('Filling textarea with query:', params.query);
await page.fill('textarea', params.query);

console.log('Clicking the button with the specified SVG...');
await page.click('button:has(svg[data-icon="arrow-right"])');

console.log(
'Waiting for the button with the specified SVG to be visible...',
);
await page.waitForSelector('button:has(svg[data-icon="arrow-right"])');

console.log('Waiting for results to load...');
await page.waitForSelector('div:has-text("Related")');

console.log('Extracting HTML content...');
const htmlContent = await page.evaluate(() => {
const resultElements = document.querySelectorAll('div[dir="auto"]');
return Array.from(resultElements)
.map((element) => element.innerHTML)
.join('\n\n');
});

console.log('Closing browser...');
await browser.close();

console.log('Converting HTML to Markdown...');
const turndownService = new TurndownService();
turndownService.addRule('preserveLinks', {
filter: 'a',
replacement: function (content, node) {
const element = node as Element;
const href = element.getAttribute('href');
return `[${content}](${href})`;
},
});
const markdown = turndownService.turndown(htmlContent);

const result: Result = {
response: markdown,
};

console.log('Returning result:', result);
return Promise.resolve({ data: result });
}
}
4 changes: 4 additions & 0 deletions apps/shinkai-tool-perplexity/tsconfig.app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"include": ["./src/**/*.ts"]
}
5 changes: 5 additions & 0 deletions apps/shinkai-tool-perplexity/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {},
"include": ["./src/**/*.ts"]
}
15 changes: 15 additions & 0 deletions apps/shinkai-tool-perplexity/tsconfig.spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"],
"lib": ["dom"]
},
"include": [
"jest.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}
19 changes: 19 additions & 0 deletions libs/shinkai-tools-runner/src/built_in_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,25 @@ lazy_static! {
)))
.unwrap(),
)),
m.insert(
"shinkai-tool-perplexity",
&*Box::leak(Box::new(
serde_json::from_str::<ToolDefinition>(include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tools/shinkai-tool-perplexity/definition.json"
)))
.unwrap(),
)),
);
m.insert(
"shinkai-tool-perplexity-api",
&*Box::leak(Box::new(
serde_json::from_str::<ToolDefinition>(include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tools/shinkai-tool-perplexity-api/definition.json"
)))
.unwrap(),
)),
);
m.insert(
"shinkai-tool-youtube-summary",
Expand Down
Loading

0 comments on commit 62961dd

Please sign in to comment.