quickquestion 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []