Skip to content

Commit

Permalink
Add perplexity search as a new tool (#7861)
Browse files Browse the repository at this point in the history
  • Loading branch information
leilei-jiang authored Sep 2, 2024
1 parent 3f2a806 commit 7193e18
Show file tree
Hide file tree
Showing 6 changed files with 326 additions and 0 deletions.
1 change: 1 addition & 0 deletions api/core/tools/provider/_position.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
- google
- bing
- perplexity
- duckduckgo
- searchapi
- serper
Expand Down
3 changes: 3 additions & 0 deletions api/core/tools/provider/builtin/perplexity/_assets/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions api/core/tools/provider/builtin/perplexity/perplexity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from typing import Any

import requests

from core.tools.errors import ToolProviderCredentialValidationError
from core.tools.provider.builtin.perplexity.tools.perplexity_search import PERPLEXITY_API_URL
from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController


class PerplexityProvider(BuiltinToolProviderController):
def _validate_credentials(self, credentials: dict[str, Any]) -> None:
headers = {
"Authorization": f"Bearer {credentials.get('perplexity_api_key')}",
"Content-Type": "application/json"
}

payload = {
"model": "llama-3.1-sonar-small-128k-online",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "Hello"
}
],
"max_tokens": 5,
"temperature": 0.1,
"top_p": 0.9,
"stream": False
}

try:
response = requests.post(PERPLEXITY_API_URL, json=payload, headers=headers)
response.raise_for_status()
except requests.RequestException as e:
raise ToolProviderCredentialValidationError(
f"Failed to validate Perplexity API key: {str(e)}"
)

if response.status_code != 200:
raise ToolProviderCredentialValidationError(
f"Perplexity API key is invalid. Status code: {response.status_code}"
)
26 changes: 26 additions & 0 deletions api/core/tools/provider/builtin/perplexity/perplexity.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
identity:
author: Dify
name: perplexity
label:
en_US: Perplexity
zh_Hans: Perplexity
description:
en_US: Perplexity.AI
zh_Hans: Perplexity.AI
icon: icon.svg
tags:
- search
credentials_for_provider:
perplexity_api_key:
type: secret-input
required: true
label:
en_US: Perplexity API key
zh_Hans: Perplexity API key
placeholder:
en_US: Please input your Perplexity API key
zh_Hans: 请输入你的 Perplexity API key
help:
en_US: Get your Perplexity API key from Perplexity
zh_Hans: 从 Perplexity 获取您的 Perplexity API key
url: https://www.perplexity.ai/settings/api
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import json
from typing import Any, Union

import requests

from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool

PERPLEXITY_API_URL = "https://api.perplexity.ai/chat/completions"

class PerplexityAITool(BuiltinTool):
def _parse_response(self, response: dict) -> dict:
"""Parse the response from Perplexity AI API"""
if 'choices' in response and len(response['choices']) > 0:
message = response['choices'][0]['message']
return {
'content': message.get('content', ''),
'role': message.get('role', ''),
'citations': response.get('citations', [])
}
else:
return {'content': 'Unable to get a valid response', 'role': 'assistant', 'citations': []}

def _invoke(self,
user_id: str,
tool_parameters: dict[str, Any],
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
headers = {
"Authorization": f"Bearer {self.runtime.credentials['perplexity_api_key']}",
"Content-Type": "application/json"
}

payload = {
"model": tool_parameters.get('model', 'llama-3.1-sonar-small-128k-online'),
"messages": [
{
"role": "system",
"content": "Be precise and concise."
},
{
"role": "user",
"content": tool_parameters['query']
}
],
"max_tokens": tool_parameters.get('max_tokens', 4096),
"temperature": tool_parameters.get('temperature', 0.7),
"top_p": tool_parameters.get('top_p', 1),
"top_k": tool_parameters.get('top_k', 5),
"presence_penalty": tool_parameters.get('presence_penalty', 0),
"frequency_penalty": tool_parameters.get('frequency_penalty', 1),
"stream": False
}

if 'search_recency_filter' in tool_parameters:
payload['search_recency_filter'] = tool_parameters['search_recency_filter']
if 'return_citations' in tool_parameters:
payload['return_citations'] = tool_parameters['return_citations']
if 'search_domain_filter' in tool_parameters:
if isinstance(tool_parameters['search_domain_filter'], str):
payload['search_domain_filter'] = [tool_parameters['search_domain_filter']]
elif isinstance(tool_parameters['search_domain_filter'], list):
payload['search_domain_filter'] = tool_parameters['search_domain_filter']


response = requests.post(url=PERPLEXITY_API_URL, json=payload, headers=headers)
response.raise_for_status()
valuable_res = self._parse_response(response.json())

return [
self.create_json_message(valuable_res),
self.create_text_message(json.dumps(valuable_res, ensure_ascii=False, indent=2))
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
identity:
name: perplexity
author: Dify
label:
en_US: Perplexity Search
description:
human:
en_US: Search information using Perplexity AI's language models.
llm: This tool is used to search information using Perplexity AI's language models.
parameters:
- name: query
type: string
required: true
label:
en_US: Query
zh_Hans: 查询
human_description:
en_US: The text query to be processed by the AI model.
zh_Hans: 要由 AI 模型处理的文本查询。
form: llm
- name: model
type: select
required: false
label:
en_US: Model Name
zh_Hans: 模型名称
human_description:
en_US: The Perplexity AI model to use for generating the response.
zh_Hans: 用于生成响应的 Perplexity AI 模型。
form: form
default: "llama-3.1-sonar-small-128k-online"
options:
- value: llama-3.1-sonar-small-128k-online
label:
en_US: llama-3.1-sonar-small-128k-online
zh_Hans: llama-3.1-sonar-small-128k-online
- value: llama-3.1-sonar-large-128k-online
label:
en_US: llama-3.1-sonar-large-128k-online
zh_Hans: llama-3.1-sonar-large-128k-online
- value: llama-3.1-sonar-huge-128k-online
label:
en_US: llama-3.1-sonar-huge-128k-online
zh_Hans: llama-3.1-sonar-huge-128k-online
- name: max_tokens
type: number
required: false
label:
en_US: Max Tokens
zh_Hans: 最大令牌数
pt_BR: Máximo de Tokens
human_description:
en_US: The maximum number of tokens to generate in the response.
zh_Hans: 在响应中生成的最大令牌数。
pt_BR: O número máximo de tokens a serem gerados na resposta.
form: form
default: 4096
min: 1
max: 4096
- name: temperature
type: number
required: false
label:
en_US: Temperature
zh_Hans: 温度
pt_BR: Temperatura
human_description:
en_US: Controls randomness in the output. Lower values make the output more focused and deterministic.
zh_Hans: 控制输出的随机性。较低的值使输出更加集中和确定。
form: form
default: 0.7
min: 0
max: 1
- name: top_k
type: number
required: false
label:
en_US: Top K
zh_Hans: 取样数量
human_description:
en_US: The number of top results to consider for response generation.
zh_Hans: 用于生成响应的顶部结果数量。
form: form
default: 5
min: 1
max: 100
- name: top_p
type: number
required: false
label:
en_US: Top P
zh_Hans: Top P
human_description:
en_US: Controls diversity via nucleus sampling.
zh_Hans: 通过核心采样控制多样性。
form: form
default: 1
min: 0.1
max: 1
step: 0.1
- name: presence_penalty
type: number
required: false
label:
en_US: Presence Penalty
zh_Hans: 存在惩罚
human_description:
en_US: Positive values penalize new tokens based on whether they appear in the text so far.
zh_Hans: 正值会根据新词元是否已经出现在文本中来对其进行惩罚。
form: form
default: 0
min: -1.0
max: 1.0
step: 0.1
- name: frequency_penalty
type: number
required: false
label:
en_US: Frequency Penalty
zh_Hans: 频率惩罚
human_description:
en_US: Positive values penalize new tokens based on their existing frequency in the text so far.
zh_Hans: 正值会根据新词元在文本中已经出现的频率来对其进行惩罚。
form: form
default: 1
min: 0.1
max: 1.0
step: 0.1
- name: return_citations
type: boolean
required: false
label:
en_US: Return Citations
zh_Hans: 返回引用
human_description:
en_US: Whether to return citations in the response.
zh_Hans: 是否在响应中返回引用。
form: form
default: true
- name: search_domain_filter
type: string
required: false
label:
en_US: Search Domain Filter
zh_Hans: 搜索域过滤器
human_description:
en_US: Domain to filter the search results.
zh_Hans: 用于过滤搜索结果的域名。
form: form
default: ""
- name: search_recency_filter
type: select
required: false
label:
en_US: Search Recency Filter
zh_Hans: 搜索时间过滤器
human_description:
en_US: Filter for search results based on recency.
zh_Hans: 基于时间筛选搜索结果。
form: form
default: "month"
options:
- value: day
label:
en_US: Day
zh_Hans:
- value: week
label:
en_US: Week
zh_Hans:
- value: month
label:
en_US: Month
zh_Hans:
- value: year
label:
en_US: Year
zh_Hans:

0 comments on commit 7193e18

Please sign in to comment.