Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
# ppxity

ppxity is a command-line tool that allows you to interact with the [Perplexity Labs (unofficial) API](https://labs.perplexity.ai/). It enables you to provide a prompt, along with a set of directories and files, and the tool will compile the content of those files into the prompt and send it to the Perplexity API.
By default, it uses the new claude-3-haiku-20240307 model.
ppxity is a command-line tool that allows you to interact with the [Perplexity API](https://docs.perplexity.ai). It enables you to provide a prompt, along with a set of directories and files, and the tool will compile the content of those files into the prompt and send it to the Perplexity API.
By default, it uses the claude-3-haiku-20240307 model.
### Why Claude 3 Haiku as default?
Firstly, it's free on [labs.perplexity.ai](https://labs.perplexity.ai) (shoutout), and secondly the benchmarking results seem to be good.
Firstly, it works well with the Perplexity API, and secondly the benchmarking results seem to be good.

![img.png](assets/img.png)

### Features
* Input Directories
* Input Files
* Backtrack
* Official Perplexity API support

### Information
This was made for personal use within a few hours, it's far from perfect, it doesn't have a fancy ui yet but I might add that sometime.

I simply wanted to be able to give claude3 a bunch of files before asking a question for better responses.
I simply wanted to be able to give the AI a bunch of files before asking a question for better responses.

### Requirements
* Perplexity API Key (get one at https://www.perplexity.ai)

### Usage
```bash
Expand All @@ -25,6 +30,7 @@ Examples:
ppxity -d C:\Users\User\GolandProjects\exampleProject -p "Explain what this project is about."

Flags:
-k, --api-key string Perplexity API key (or set PPLX_API_KEY environment variable)
-D, --debug Enable debug mode
-d, --directories strings Directories to use for the initial prompt
-e, --extensions strings Allowed file extensions to use for the initial prompt (default [go,txt,mod,cs,c,rs,js,ts])
Expand All @@ -40,12 +46,27 @@ Flags:

```bash
git clone https://github.com/0xInception/ppxity
go run main.go -p "What is this project about?" -d /path/to/directory
go run main.go -p "What is this project about?" -d /path/to/directory --api-key your_api_key_here -m "llama-3.1-sonar-small-128k-online"
```
or

or set environment variable:

```bash
ppxity.exe -p "What is this project about?" -d C:\path\to\directory -f C:\path\to\file.go -f C:\path\to\another\file.go
export PPLX_API_KEY=your_api_key_here
go run main.go -p "What is this project about?" -d /path/to/directory -m "llama-3.1-sonar-small-128k-online"
```

Alternative:
```bash
ppxity.exe -p "What is this project about?" -d C:\path\to\directory -f C:\path\to\file.go -f C:\path\to\another\file.go --api-key your_api_key_here -m "llama-3.1-sonar-small-128k-online"
```

### Important Note on Model Selection
Model availability depends on your Perplexity API subscription plan. Common models include:
- Free tier: `llama-3.1-sonar-small-128k-online`, `llama-3.1-sonar-large-128k-online`
- Paid tier: Additional models like `claude-sonnet-4-29339`, `gpt-4o`, etc.

Check the [Perplexity API documentation](https://docs.perplexity.ai/getting-started/models) for the complete list of models available to your API key.

### License
MIT
58 changes: 24 additions & 34 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var model string
var promptText string
var debug bool
var showInitialPrompt bool
var apiKey string

// var conversationMode bool
var timeout int
Expand Down Expand Up @@ -49,42 +50,42 @@ var rootCmd = &cobra.Command{
}

ppxity := perplexity.NewChatClient(debug, false)

// Set API key from flag or environment variable
if apiKey == "" {
apiKey = os.Getenv("PPLX_API_KEY")
}
if apiKey == "" {
log.Fatal("Error: API key not provided. Set --api-key flag or PPLX_API_KEY environment variable")
}
ppxity.SetAPIKey(apiKey)

err = ppxity.Connect()
if err != nil {
log.Fatalf("Error: %s", err)
return
}
defer ppxity.Close()

// Send the initial message
err = ppxity.SendMessage(comp, model)
if err != nil {
log.Fatalf("Error: %s", err)
return
}

// Get the response directly
resp := ppxity.GetLastResponse()

if !showInitialPrompt {
fmt.Println("User: Initial prompt sent")
} else {
log.Println("User: " + comp)
}
var resp string
for i := 0; i < 10; i++ {
partialResp, err := ppxity.ReceiveMessage(time.Second * time.Duration(timeout))
if err != nil {
log.Println(fmt.Sprintf("Failed to receive message: %v", err))
break
}
resp += partialResp
if strings.HasSuffix(resp, "<end>") {
log.Println("Attempts:", i+1)
break
} else {
err = ppxity.SendMessage("Continue EXACTLY where you left off without any other text at start.", model)
if err != nil {
log.Fatalf("Error: %s", err)
return
}
}
}

// Handle continuation if needed (for longer responses)
// Note: This approach is different from the original socket.io version
// The new API returns complete responses in one call
fmt.Println("Assistant:\r\n" + resp + "\r\n\r\n")

handleUserInput(ppxity, model, time.Second*time.Duration(timeout))
Expand All @@ -95,8 +96,9 @@ func init() {
rootCmd.Flags().StringSliceVarP(&directories, "directories", "d", []string{}, "Directories to use for the initial prompt")
rootCmd.Flags().StringSliceVarP(&files, "files", "f", []string{}, "Files to use for the initial prompt")
rootCmd.Flags().StringSliceVarP(&extensions, "extensions", "e", []string{"go", "txt", "mod", "cs", "c", "rs", "js", "ts"}, "Allowed file extensions to use for the initial prompt")
rootCmd.Flags().StringVarP(&model, "model", "m", perplexity.CLAUDE, "Perplexity model to use: e.g. 'claude-3-haiku-20240307' ("+strings.Join(perplexity.ALL_MODELS, ", ")+")")
rootCmd.Flags().StringVarP(&model, "model", "m", perplexity.CLAUDE, "Perplexity model to use: e.g. '"+perplexity.CLAUDE+"' ("+strings.Join(perplexity.ALL_MODELS, ", ")+")")
rootCmd.Flags().StringVarP(&promptText, "prompt", "p", "", "Initial prompt for the conversation: e.g. 'Hello, World!'")
rootCmd.Flags().StringVarP(&apiKey, "api-key", "k", "", "Perplexity API key (or set PPLX_API_KEY environment variable)")
rootCmd.Flags().BoolVarP(&debug, "debug", "D", false, "Enable debug mode")
rootCmd.Flags().BoolVarP(&showInitialPrompt, "show-initial-prompt", "s", false, "Show the initial prompt")
//rootCmd.Flags().BoolVarP(&conversationMode, "conversation", "C", false, "Enable conversation mode")
Expand Down Expand Up @@ -131,20 +133,8 @@ func handleUserInput(ppxity *perplexity.ChatClient, model string, timeout time.D
continue
}

var resp string
for i := 0; i < 20; i++ {
partialResp, err := ppxity.ReceiveMessage(timeout)
if err != nil {
log.Println(fmt.Sprintf("Failed to receive message: %v", err))
break
}
resp += partialResp
if strings.HasSuffix(resp, "<end>") {
break
}
}

// Get the response directly
resp := ppxity.GetLastResponse()
fmt.Println(resp)

}
}
Loading