llmed 0.3.19 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 26f64ce9f1d2a1fb5bf48f03b29d8655e920fbf35bc52d7f88dd62b0484e46bc
4
- data.tar.gz: 225854a7506247a8ef9de98d63c3615b8fe92caeb79dc5a6228739102652560a
3
+ metadata.gz: 26dd1afcf05c5f3a999d02d330f1888f15fadb57546cea5f793d3aa942f22a0f
4
+ data.tar.gz: 8e387a3afa41e2caa5def2241a49e59b85b893f76028f2d317d085e01a0f3826
5
5
  SHA512:
6
- metadata.gz: 5a317a663ed4c396469c4c7e082b19ab92d8633ce31ed022b8b1a3c90cc61635bac218d42eaf942c6508a643fffb5906d9a682a8962b11d151358dcb104975d4
7
- data.tar.gz: 4c1347a274c421b2a9b7f04d5a2d7f63e78f8397d71be39ad34e3288c78c935e60a75a2f3c38bf6470d1bba11c3ab4be3c7e7712bcf4d984070f576fbb65d7de
6
+ metadata.gz: 12a72fca1b9f9a8678dcc753c66a5c8cfe58086326b8232f89a19310c6227d3775daa402e7586ab2ce457611265b751b01b7345dee5a19b5784590cf3c9dbc0c
7
+ data.tar.gz: 9b2f6abe791e5c969975675a06385bbf996ef6bf5826e64f7093715f56ef3aa60e8e55a236b1051cc71392b5c3972aaeffd0d241b14c14213f8d5312ffeabc39
data/README.md CHANGED
@@ -39,6 +39,33 @@ application "MINI COUNTER", release: nil, language: :node, output_file: "minicou
39
39
  end
40
40
  end
41
41
 
42
+ ```
43
+
44
+ Since version 0.4.0, literate programming was introduced, and it is now possible to write code using a markdown-like syntax.
45
+
46
+ ```md
47
+ #!language ruby
48
+ #% increase release once you agree with the change
49
+ #!environment release
50
+ #!environment output_file minicounter.rb
51
+
52
+ # Dependencies
53
+
54
+ * Must use only the standard/native library.
55
+ * Must not use external dependencies.
56
+
57
+ # API
58
+
59
+ API Server listening port 3007.
60
+ Expose the following endpoints:
61
+ - GET /count
62
+ - return the latest count.
63
+ - POST /count
64
+ - increase the count by 1.
65
+ add CORS endpoints.
66
+ ```
67
+ then compile using command `llmed.literate`.
68
+
42
69
  ## Programming flow
43
70
 
44
71
  * Cycle
@@ -0,0 +1,68 @@
1
+ #!/bin/env ruby
2
+ # Copyright 2025 Jovany Leandro G.C <bit4bit@riseup.net>
3
+ # frozen_string_literal: true
4
+ require 'optparse'
5
+ require 'llmed'
6
+
7
+ logger = Logger.new(STDERR)
8
+ output_dir = './llmed-out'
9
+ release_dir = output_dir
10
+ language = 'ruby'
11
+ provider = :like_openai
12
+ provider_api_key = ENV.fetch('LLMED_PROVIDER_API_KEY', nil)
13
+ provider_model = ENV.fetch('LLMED_PROVIDER_MODEL', 'Qwen/Qwen2.5-Coder-32B-Instruct')
14
+ provider_uri_base = ENV.fetch('LLMED_PROVIDER_URI_BASE', 'https://api.together.xyz/v1')
15
+ output_file = 'a.out.ollmed'
16
+
17
+ template = <<~TMP
18
+ # Main
19
+
20
+ Show to user 'hi world!'.
21
+ TMP
22
+
23
+ OptionParser.new do |parser|
24
+ parser.banner = "Usage: llmed.literate [options] <application file .llmed.literate or stdin>"
25
+ parser.on_tail("-h", "--help", "Show this message") do
26
+ puts parser
27
+ puts "\n# Website\nhttps://github.com/bit4bit/llm-labs/tree/main/llmed"
28
+ puts "\n# Examples\nhttps://github.com/bit4bit/llm-labs/tree/main/llmed/examples"
29
+ puts "Environment vars:\nLLMED_PROVIDER_API_KEY\nLLMED_PROVIDER_MODEL=#{provider_model}\nLLMED_PROVIDER_URI_BASE=#{provider_uri_base}"
30
+ exit
31
+ end
32
+
33
+ parser.on('-t', '--template PATH', String, 'Create template') do |path|
34
+ File.write path, template
35
+ exit
36
+ end
37
+
38
+ parser.on('-c', '--compile PATH', String, 'Output compiled') do |path|
39
+ output_file = path
40
+ end
41
+
42
+ parser.on('--output-dir DIR', String) do |path|
43
+ output_dir = path
44
+ end
45
+
46
+ parser.on('--release-dir DIR', String) do |path|
47
+ release_dir = path
48
+ end
49
+
50
+ parser.on('-l', '--language LANGUAGE', String, 'Programming Language: ruby, python') do |lang|
51
+ language = lang
52
+ end
53
+
54
+ parser.on('-q', '--quiet') do
55
+ logger.level = :error
56
+ end
57
+ end.parse!
58
+
59
+ source_code = ARGF.read
60
+ if ARGF.respond_to?(:path)
61
+ release_dir = File.dirname(ARGF.path)
62
+ end
63
+
64
+ llmed = LLMed.new(logger: logger, output_dir: output_dir, release_dir: release_dir)
65
+ llmed.set_language language
66
+ llmed.set_llm provider: provider, api_key: provider_api_key, model: provider_model, options: {uri_base: provider_uri_base}
67
+ LLMed::LiterateProgramming.execute(llmed, 'literate_programming', source_code, output_file: output_file)
68
+ llmed.compile()
@@ -57,7 +57,7 @@ class LLMed
57
57
  end
58
58
 
59
59
  def prepare
60
- @logger.info("APPLICATION #{@name} COMPILING FOR #{@language}")
60
+ @logger.info("APPLICATION #{@name} COMPILING FOR #{@language} RELEASE #{@release}")
61
61
  return unless @output_file.is_a?(String)
62
62
  return unless @release
63
63
 
@@ -1,4 +1,4 @@
1
- #<llmed-code context='Library LLMed::LiterateProgramming::Markdown' digest='18aa5391a8a334f24a80542620a277bb9c085762cb88b7dbcafa26a532a48027' after=''>
1
+ #<llmed-code context='Library LLMed::LiterateProgramming::Markdown' digest='9c0e3f61ab4cdc3c56c29230a800487dd1a7ef0d929c843fd2461907d0831ab2' after=''>
2
2
  class LLMed::LiterateProgramming::Markdown
3
3
  def parse(input)
4
4
  contexts = []
@@ -12,6 +12,8 @@ class LLMed::LiterateProgramming::Markdown
12
12
  current_context[:content] << { type: :link, content: Regexp.last_match(1), reference: Regexp.last_match(2) }
13
13
  elsif line.strip =~ /^#% (.+)$/
14
14
  current_context[:content] << { type: :comment, content: Regexp.last_match(1) + "\n" }
15
+ elsif line.strip =~ /^#!environment\s+(\w+)\s+(.+)$/
16
+ current_context[:content] << { type: :environment, name: Regexp.last_match(1), value: Regexp.last_match(2) }
15
17
  else
16
18
  current_context[:content] << { type: :string, content: line }
17
19
  end
@@ -0,0 +1,24 @@
1
+ #<llmed-code context='Library LLMed::LiterateProgramming::Markdown' digest='18aa5391a8a334f24a80542620a277bb9c085762cb88b7dbcafa26a532a48027' after=''>
2
+ class LLMed::LiterateProgramming::Markdown
3
+ def parse(input)
4
+ contexts = []
5
+ current_context = { type: :context, title: "_default", content: [] }
6
+
7
+ input.each_line do |line|
8
+ if line.strip =~ /^# (.+)$/
9
+ contexts << current_context unless current_context[:content].empty?
10
+ current_context = { type: :context, title: Regexp.last_match(1), content: [] }
11
+ elsif line.strip =~ /^\[(.+)\]\((.+)\)$/
12
+ current_context[:content] << { type: :link, content: Regexp.last_match(1), reference: Regexp.last_match(2) }
13
+ elsif line.strip =~ /^#% (.+)$/
14
+ current_context[:content] << { type: :comment, content: Regexp.last_match(1) + "\n" }
15
+ else
16
+ current_context[:content] << { type: :string, content: line }
17
+ end
18
+ end
19
+
20
+ contexts << current_context unless current_context[:content].empty?
21
+ contexts
22
+ end
23
+ end
24
+ #</llmed-code>
@@ -0,0 +1,24 @@
1
+ #<llmed-code context='Library LLMed::LiterateProgramming::Markdown' digest='18aa5391a8a334f24a80542620a277bb9c085762cb88b7dbcafa26a532a48027' after=''>
2
+ class LLMed::LiterateProgramming::Markdown
3
+ def parse(input)
4
+ contexts = []
5
+ current_context = { type: :context, title: "_default", content: [] }
6
+
7
+ input.each_line do |line|
8
+ if line.strip =~ /^# (.+)$/
9
+ contexts << current_context unless current_context[:content].empty?
10
+ current_context = { type: :context, title: Regexp.last_match(1), content: [] }
11
+ elsif line.strip =~ /^\[(.+)\]\((.+)\)$/
12
+ current_context[:content] << { type: :link, content: Regexp.last_match(1), reference: Regexp.last_match(2) }
13
+ elsif line.strip =~ /^#% (.+)$/
14
+ current_context[:content] << { type: :comment, content: Regexp.last_match(1) + "\n" }
15
+ else
16
+ current_context[:content] << { type: :string, content: line }
17
+ end
18
+ end
19
+
20
+ contexts << current_context unless current_context[:content].empty?
21
+ contexts
22
+ end
23
+ end
24
+ #</llmed-code>
@@ -0,0 +1,37 @@
1
+ {"inserted_at":1750948592,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":null,"total_tokens":801,"duration_seconds":7}
2
+ {"inserted_at":1750948631,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":null,"total_tokens":802,"duration_seconds":10}
3
+ {"inserted_at":1750948668,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":null,"total_tokens":802,"duration_seconds":8}
4
+ {"inserted_at":1750948715,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":null,"total_tokens":789,"duration_seconds":7}
5
+ {"inserted_at":1750948827,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":null,"total_tokens":815,"duration_seconds":9}
6
+ {"inserted_at":1750948952,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":752,"duration_seconds":7}
7
+ {"inserted_at":1750948976,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":799,"duration_seconds":5}
8
+ {"inserted_at":1750949014,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":766,"duration_seconds":6}
9
+ {"inserted_at":1750949045,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":810,"duration_seconds":5}
10
+ {"inserted_at":1750949073,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":765,"duration_seconds":5}
11
+ {"inserted_at":1750949098,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":761,"duration_seconds":5}
12
+ {"inserted_at":1750949120,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":794,"duration_seconds":6}
13
+ {"inserted_at":1750949132,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":764,"duration_seconds":4}
14
+ {"inserted_at":1750949163,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":772,"duration_seconds":4}
15
+ {"inserted_at":1750949215,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":793,"duration_seconds":7}
16
+ {"inserted_at":1750949230,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":793,"duration_seconds":6}
17
+ {"inserted_at":1750949263,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":786,"duration_seconds":5}
18
+ {"inserted_at":1750949274,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":790,"duration_seconds":5}
19
+ {"inserted_at":1750949300,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":809,"duration_seconds":11}
20
+ {"inserted_at":1750949341,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":767,"duration_seconds":5}
21
+ {"inserted_at":1750949462,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":749,"duration_seconds":4}
22
+ {"inserted_at":1750949604,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":761,"duration_seconds":5}
23
+ {"inserted_at":1750949637,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":735,"duration_seconds":7}
24
+ {"inserted_at":1750949713,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":756,"duration_seconds":4}
25
+ {"inserted_at":1750949955,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":null,"total_tokens":1021,"duration_seconds":5}
26
+ {"inserted_at":1750950487,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":1,"total_tokens":1575,"duration_seconds":5}
27
+ {"inserted_at":1750950574,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":1,"total_tokens":1571,"duration_seconds":5}
28
+ {"inserted_at":1750948249,"name":"Literate Programming Markdown","provider":"like_openai","model":"Qwen/Qwen2.5-Coder-32B-Instruct","release":null,"total_tokens":825,"duration_seconds":6}
29
+ {"inserted_at":1751277383,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":1,"total_tokens":2438,"duration_seconds":17}
30
+ {"inserted_at":1751277514,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":1,"total_tokens":2438,"duration_seconds":19}
31
+ {"inserted_at":1751277672,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":1,"total_tokens":2417,"duration_seconds":18}
32
+ {"inserted_at":1751277767,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":1,"total_tokens":1833,"duration_seconds":9}
33
+ {"inserted_at":1751278515,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":1,"total_tokens":2416,"duration_seconds":19}
34
+ {"inserted_at":1751278535,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":1,"total_tokens":2396,"duration_seconds":13}
35
+ {"inserted_at":1751278560,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":1,"total_tokens":2416,"duration_seconds":18}
36
+ {"inserted_at":1751278598,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o-mini","release":1,"total_tokens":2416,"duration_seconds":15}
37
+ {"inserted_at":1751278618,"name":"Literate Programming Markdown","provider":"openai","model":"gpt-4o","release":1,"total_tokens":1830,"duration_seconds":6}
@@ -1,6 +1,53 @@
1
+ require 'open-uri'
1
2
 
2
3
  class LLMed
3
4
  class LiterateProgramming
5
+ def self.execute(llmed, application_name, code, **application_args)
6
+ md = LLMed::LiterateProgramming::Markdown.new()
7
+ contexts = []
8
+
9
+ md.parse(code).each do |item|
10
+ context = {}
11
+
12
+ if item[:title] == "_default"
13
+ item[:content].each do |item_content|
14
+ case item_content[:type]
15
+ when :environment
16
+ name = item_content[:name].strip.to_sym
17
+ value = item_content[:value].strip
18
+ if [:language, :release, :output_file, :output_dir, :release_dir].include?(name) && !value.empty?
19
+ application_args[name] = value
20
+ end
21
+ end
22
+ end
23
+ next
24
+ end
25
+
26
+ case item[:type]
27
+ when :context
28
+ context[:title] = item[:title]
29
+ context[:content] = ''
30
+
31
+ item[:content].each do |item_content|
32
+ case item_content[:type]
33
+ when :comment
34
+ next
35
+ when :string
36
+ context[:content] += item_content[:content]
37
+ when :link
38
+ context[:content] += "#{URI.open(item_content[:reference]).read}\n"
39
+ end
40
+ end
41
+ contexts << context
42
+ end
43
+ end
44
+
45
+ llmed.application(application_name, **application_args) do
46
+ contexts.each do |lcontext|
47
+ context(lcontext[:title]) { lcontext[:content] }
48
+ end
49
+ end
50
+ end
4
51
  end
5
52
  end
6
53
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: llmed
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.19
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jovany Leandro G.C
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-06-26 00:00:00.000000000 Z
11
+ date: 2025-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: langchainrb
@@ -86,12 +86,14 @@ description: Use this 'compiler' to build software using LLMs in a controlled wa
86
86
  email: bit4bit@riseup.net
87
87
  executables:
88
88
  - llmed
89
+ - llmed.literate
89
90
  extensions: []
90
91
  extra_rdoc_files: []
91
92
  files:
92
93
  - LICENSE
93
94
  - README.md
94
95
  - exe/llmed
96
+ - exe/llmed.literate
95
97
  - lib/literate_programming.llmed~
96
98
  - lib/llm.rb
97
99
  - lib/llm.rb~
@@ -108,7 +110,9 @@ files:
108
110
  - lib/llmed/literate_programming.rb
109
111
  - lib/llmed/literate_programming.rb~
110
112
  - lib/llmed/literate_programming/markdown.rb
111
- - lib/llmed/markdown.rb.statistics
113
+ - lib/llmed/literate_programming/markdown.rb.r1ruby.cache
114
+ - lib/llmed/literate_programming/markdown.rb.release
115
+ - lib/llmed/literate_programming/markdown.rb.statistics
112
116
  - lib/llmed/release.rb
113
117
  - lib/llmed/release.rb~
114
118
  homepage: https://github.com/bit4bit/llmed
@@ -1 +0,0 @@
1
- {"inserted_at":1750948249,"name":"Literate Programming Markdown","provider":"like_openai","model":"Qwen/Qwen2.5-Coder-32B-Instruct","release":null,"total_tokens":825,"duration_seconds":6}