quickquestion 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.git-blame-ignore-revs +0 -0
- data/.gitignore +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +104 -0
- data/README.md +54 -0
- data/bin/qq +23 -0
- data/lib/migration/20240811233902_create_queries_table.rb +17 -0
- data/lib/quickquestion.rb +58 -0
- data/quickquestion.gemspec +25 -0
- metadata +56 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c713eb0d5a8fce0fb8b796e7984b0c2c27e34c89fda6cffac8ce1f8d6d6fce6d
|
4
|
+
data.tar.gz: 3016f0aa46f0507982cbc190d55a2f9a2f90881df176a6ce750c51ebf943e604
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b2e252409b9ad5cd35b451d795c47b0ec642443b8845d162b0017caa3e6a90001a2c580dce94f484d77b2fb6a7f383fa9b134286c59e1ff7136d7ce6cb00a90e
|
7
|
+
data.tar.gz: 66b4afda992913ae14816a70ece7ad905cb0d691db997aaff79d2bac9ce9e1ca07e073aed57fb474efdf53a057cbbc21628730732526cecf36a4d60f91dfe710
|
File without changes
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.3.1
|
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :development do
|
6
|
+
gem "byebug"
|
7
|
+
gem "rb-readline"
|
8
|
+
gem "standard"
|
9
|
+
gem "standard-performance"
|
10
|
+
end
|
11
|
+
|
12
|
+
# runtime dependencies
|
13
|
+
gem "claude-ruby"
|
14
|
+
gem "sequel"
|
15
|
+
gem "sqlite3"
|
16
|
+
gem "xdg"
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
quickquestion (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ast (2.4.2)
|
10
|
+
bigdecimal (3.1.8)
|
11
|
+
byebug (11.1.3)
|
12
|
+
claude-ruby (0.4.0)
|
13
|
+
httparty
|
14
|
+
csv (3.3.0)
|
15
|
+
httparty (0.22.0)
|
16
|
+
csv
|
17
|
+
mini_mime (>= 1.0.0)
|
18
|
+
multi_xml (>= 0.5.2)
|
19
|
+
json (2.7.2)
|
20
|
+
language_server-protocol (3.17.0.3)
|
21
|
+
lint_roller (1.1.0)
|
22
|
+
mini_mime (1.1.5)
|
23
|
+
multi_xml (0.7.1)
|
24
|
+
bigdecimal (~> 3.1)
|
25
|
+
parallel (1.26.2)
|
26
|
+
parser (3.3.4.2)
|
27
|
+
ast (~> 2.4.1)
|
28
|
+
racc
|
29
|
+
racc (1.8.1)
|
30
|
+
rainbow (3.1.1)
|
31
|
+
rb-readline (0.5.5)
|
32
|
+
regexp_parser (2.9.2)
|
33
|
+
rexml (3.3.5)
|
34
|
+
strscan
|
35
|
+
rubocop (1.64.1)
|
36
|
+
json (~> 2.3)
|
37
|
+
language_server-protocol (>= 3.17.0)
|
38
|
+
parallel (~> 1.10)
|
39
|
+
parser (>= 3.3.0.2)
|
40
|
+
rainbow (>= 2.2.2, < 4.0)
|
41
|
+
regexp_parser (>= 1.8, < 3.0)
|
42
|
+
rexml (>= 3.2.5, < 4.0)
|
43
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
44
|
+
ruby-progressbar (~> 1.7)
|
45
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
46
|
+
rubocop-ast (1.32.0)
|
47
|
+
parser (>= 3.3.1.0)
|
48
|
+
rubocop-performance (1.21.1)
|
49
|
+
rubocop (>= 1.48.1, < 2.0)
|
50
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
51
|
+
ruby-progressbar (1.13.0)
|
52
|
+
sequel (5.83.1)
|
53
|
+
bigdecimal
|
54
|
+
sqlite3 (2.0.3-aarch64-linux-gnu)
|
55
|
+
sqlite3 (2.0.3-aarch64-linux-musl)
|
56
|
+
sqlite3 (2.0.3-arm-linux-gnu)
|
57
|
+
sqlite3 (2.0.3-arm-linux-musl)
|
58
|
+
sqlite3 (2.0.3-arm64-darwin)
|
59
|
+
sqlite3 (2.0.3-x86-linux-gnu)
|
60
|
+
sqlite3 (2.0.3-x86-linux-musl)
|
61
|
+
sqlite3 (2.0.3-x86_64-darwin)
|
62
|
+
sqlite3 (2.0.3-x86_64-linux-gnu)
|
63
|
+
sqlite3 (2.0.3-x86_64-linux-musl)
|
64
|
+
standard (1.39.2)
|
65
|
+
language_server-protocol (~> 3.17.0.2)
|
66
|
+
lint_roller (~> 1.0)
|
67
|
+
rubocop (~> 1.64.0)
|
68
|
+
standard-custom (~> 1.0.0)
|
69
|
+
standard-performance (~> 1.4)
|
70
|
+
standard-custom (1.0.2)
|
71
|
+
lint_roller (~> 1.0)
|
72
|
+
rubocop (~> 1.50)
|
73
|
+
standard-performance (1.4.0)
|
74
|
+
lint_roller (~> 1.1)
|
75
|
+
rubocop-performance (~> 1.21.0)
|
76
|
+
strscan (3.1.0)
|
77
|
+
unicode-display_width (2.5.0)
|
78
|
+
xdg (8.5.0)
|
79
|
+
|
80
|
+
PLATFORMS
|
81
|
+
aarch64-linux-gnu
|
82
|
+
aarch64-linux-musl
|
83
|
+
arm-linux-gnu
|
84
|
+
arm-linux-musl
|
85
|
+
arm64-darwin
|
86
|
+
x86-linux-gnu
|
87
|
+
x86-linux-musl
|
88
|
+
x86_64-darwin
|
89
|
+
x86_64-linux-gnu
|
90
|
+
x86_64-linux-musl
|
91
|
+
|
92
|
+
DEPENDENCIES
|
93
|
+
byebug
|
94
|
+
claude-ruby
|
95
|
+
quickquestion!
|
96
|
+
rb-readline
|
97
|
+
sequel
|
98
|
+
sqlite3
|
99
|
+
standard
|
100
|
+
standard-performance
|
101
|
+
xdg
|
102
|
+
|
103
|
+
BUNDLED WITH
|
104
|
+
2.5.9
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Quick Question...
|
2
|
+
|
3
|
+
Ask Claude a quick question from the CLI with `qq`:
|
4
|
+
|
5
|
+
$ qq how do I tell if I'm using an rbenv ruby or the system ruby
|
6
|
+
$ cat question.txt | qq
|
7
|
+
$ echo "question" | qq
|
8
|
+
|
9
|
+
# or just qq alone for a prompt with readline:
|
10
|
+
$ qq
|
11
|
+
> is rbenv or chruby more reliable?
|
12
|
+
|
13
|
+
Set `ANTHROPIC_API_KEY` env var to your [API key](https://console.anthropic.com/account/keys).
|
14
|
+
|
15
|
+
## Expectations
|
16
|
+
|
17
|
+
`qq` is a quick hack.
|
18
|
+
There are currently no options.
|
19
|
+
|
20
|
+
Your questions and answers are logged to `~/.config/qq/log.sqlite`
|
21
|
+
(or set [XDG_CCONFIG_HOME](https://specifications.freedesktop.org/basedir-spec/latest/#variables)).
|
22
|
+
|
23
|
+
## Possible TODOs
|
24
|
+
|
25
|
+
* Handle ctrl-c without traceback
|
26
|
+
* Prompt customization.
|
27
|
+
* Use `qc` to have a quick conversation (or `quick continue`), which picks up from the last `qq` if it happened in the last 15m.
|
28
|
+
(This uses the logs in `~/.config/qq/log.sqlite`.)
|
29
|
+
* Prompt for a response in tags. Use `stop_sequences` to end abruptly.
|
30
|
+
* https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching
|
31
|
+
|
32
|
+
## Development
|
33
|
+
|
34
|
+
# run local
|
35
|
+
ruby -Ilib bin/qq
|
36
|
+
|
37
|
+
# irb with gem loaded
|
38
|
+
irb -Ilib -rqq
|
39
|
+
|
40
|
+
## Local use
|
41
|
+
|
42
|
+
# after build
|
43
|
+
gem install ./qq-<tab>
|
44
|
+
|
45
|
+
# Release
|
46
|
+
|
47
|
+
# rm old gems
|
48
|
+
rm *.gem
|
49
|
+
|
50
|
+
# set version in qq.gemspec
|
51
|
+
|
52
|
+
# to make the .gem
|
53
|
+
gem build
|
54
|
+
|
data/bin/qq
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Ruby 3.4 will move csv out of stdlib; httparty 0.22.0 depends on it without a version, bundler is
|
4
|
+
# confused/mad there is a stdlib and gem version at the same time, warning:
|
5
|
+
# WARN: Unresolved or ambiguous specs during Gem::Specification.reset:
|
6
|
+
# csv (>= 0)
|
7
|
+
# Available/installed versions of this gem:
|
8
|
+
# - 3.3.0
|
9
|
+
# - 3.2.8
|
10
|
+
# WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'
|
11
|
+
# Please report a bug if this causes problems.
|
12
|
+
# requiring csv here silences it and I refuse to keep digging
|
13
|
+
require "csv"
|
14
|
+
|
15
|
+
require "bundler/setup"
|
16
|
+
|
17
|
+
require "readline"
|
18
|
+
require "quickquestion"
|
19
|
+
|
20
|
+
input = ARGV.any? ? ARGV.join(' ') : ($stdin.tty? ? Readline.readline("> ", true) : $stdin.read)
|
21
|
+
exit if input.nil? || input.strip.empty?
|
22
|
+
response = QuickQuestion.query(input)
|
23
|
+
puts response
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Sequel.migration do
|
2
|
+
up do
|
3
|
+
create_table(:queries) do
|
4
|
+
primary_key :id
|
5
|
+
DateTime :at, null: false
|
6
|
+
String :query, null: false
|
7
|
+
String :response, null: false
|
8
|
+
Integer :input_tokens, null: false
|
9
|
+
Integer :output_tokens, null: false
|
10
|
+
BigDecimal :cost, size: [10, 4], null: false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
down do
|
15
|
+
drop_table(:queries)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "claude/client"
|
2
|
+
require "sequel"
|
3
|
+
require "fileutils"
|
4
|
+
require "xdg"
|
5
|
+
require "bigdecimal"
|
6
|
+
|
7
|
+
module QuickQuestion
|
8
|
+
VERSION = "0.1.0"
|
9
|
+
DB_PATH = File.join(XDG::Config.new.home, "qq/log.sqlite3")
|
10
|
+
|
11
|
+
def self.setup_db
|
12
|
+
FileUtils.mkdir_p(File.dirname(DB_PATH))
|
13
|
+
@db ||= Sequel.connect("sqlite://#{DB_PATH}")
|
14
|
+
|
15
|
+
Sequel.extension :migration
|
16
|
+
Sequel::TimestampMigrator.run(@db, File.join(File.dirname(__FILE__), "migration"))
|
17
|
+
|
18
|
+
@db
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.db
|
22
|
+
@db ||= setup_db
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.query(input)
|
26
|
+
api_key = ENV["ANTHROPIC_API_KEY"]
|
27
|
+
raise "ANTHROPIC_API_KEY environment variable is not set" if api_key.nil? || api_key.empty?
|
28
|
+
|
29
|
+
claude = Claude::Client.new(api_key)
|
30
|
+
prompt = "Give concise expert answers. Answer calmly and directly. If unsure, answer about the most common case. Never repeat questions or introduce your answer. If giving code samples, do not explain unless explicitly asked."
|
31
|
+
messages = claude.user_message(prompt + "\n" + input)
|
32
|
+
response = claude.messages(messages, model: Claude::Model::CLAUDE_SONNET_LATEST)
|
33
|
+
text = claude.parse_response(response)
|
34
|
+
usage = response["usage"]
|
35
|
+
input_tokens = usage["input_tokens"]
|
36
|
+
output_tokens = usage["output_tokens"]
|
37
|
+
cost = calculate_cost(usage)
|
38
|
+
log_query(input, text, input_tokens, output_tokens, cost)
|
39
|
+
"#{text} (Cost: $#{cost.truncate(4).to_s("F")})"
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.calculate_cost(usage)
|
43
|
+
input_tokens = BigDecimal(usage["input_tokens"])
|
44
|
+
output_tokens = BigDecimal(usage["output_tokens"])
|
45
|
+
(input_tokens * 3 + output_tokens * 15) / BigDecimal("1_000_000")
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.log_query(query, response, input_tokens, output_tokens, cost)
|
49
|
+
db[:queries].insert(
|
50
|
+
at: Time.now.utc,
|
51
|
+
query: query,
|
52
|
+
response: response,
|
53
|
+
input_tokens: input_tokens,
|
54
|
+
output_tokens: output_tokens,
|
55
|
+
cost: cost
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative "lib/quickquestion"
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "quickquestion"
|
5
|
+
spec.version = QuickQuestion::VERSION
|
6
|
+
spec.required_ruby_version = ">= 3.0.0"
|
7
|
+
spec.summary = "Ask LLMs quick questions"
|
8
|
+
spec.description = "A command-line tool to quickly ask questions to LLMs"
|
9
|
+
spec.authors = ["Peter Bhat Harkins"]
|
10
|
+
spec.email = ["peter@push.cx"]
|
11
|
+
spec.license = "Nonstandard" # yeah I dunno
|
12
|
+
|
13
|
+
spec.homepage = "https://push.cx/qq"
|
14
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
15
|
+
spec.metadata["source_code_uri"] = "https://github.com/pushcx/quickquestion"
|
16
|
+
|
17
|
+
spec.files = Dir.chdir(__dir__) do
|
18
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
19
|
+
f.start_with?("test/", "spec/")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
spec.bindir = "bin"
|
23
|
+
spec.executables = ["qq"]
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: quickquestion
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Peter Bhat Harkins
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-11-15 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A command-line tool to quickly ask questions to LLMs
|
14
|
+
email:
|
15
|
+
- peter@push.cx
|
16
|
+
executables:
|
17
|
+
- qq
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- ".git-blame-ignore-revs"
|
22
|
+
- ".gitignore"
|
23
|
+
- ".ruby-version"
|
24
|
+
- Gemfile
|
25
|
+
- Gemfile.lock
|
26
|
+
- README.md
|
27
|
+
- bin/qq
|
28
|
+
- lib/migration/20240811233902_create_queries_table.rb
|
29
|
+
- lib/quickquestion.rb
|
30
|
+
- quickquestion.gemspec
|
31
|
+
homepage: https://push.cx/qq
|
32
|
+
licenses:
|
33
|
+
- Nonstandard
|
34
|
+
metadata:
|
35
|
+
homepage_uri: https://push.cx/qq
|
36
|
+
source_code_uri: https://github.com/pushcx/quickquestion
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 3.0.0
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubygems_version: 3.5.20
|
53
|
+
signing_key:
|
54
|
+
specification_version: 4
|
55
|
+
summary: Ask LLMs quick questions
|
56
|
+
test_files: []
|