llm_conductor 0.1.1 → 1.0.0

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: c1b006030ac01906369f830f2c11d958f40c3bf3a48404179d78c6b1e75a82e5
4
- data.tar.gz: 7ccf09702230675a381f164f4ccb91034aec880c5769cb8887711c6737385c46
3
+ metadata.gz: c692236c5d26b598a2275a3a6591022312aec4e4a4d4ee57a186abc774bc39ce
4
+ data.tar.gz: 3c20edc85442b8e5227fb6896d3899f08495fa1296306042c07c8bc62a883941
5
5
  SHA512:
6
- metadata.gz: 4c3283602c064e5c7e67ac5a1b26353c936b9d5d351ad21d87a89058aa045af1f8f916f350ac07db4a0405a6fe9091b09ecc00b091afd57039d3ae560bd199e8
7
- data.tar.gz: 571400d81fa8029ecf9f9d4a53c48ac26392c13de927994c358b0e953d27257b94ff929f1d65f13b64ccddaada8785e33f271b4cf99ebdad74c63abef3dd4a97
6
+ metadata.gz: 8ed23461382c3a8ee2fddea05fdaef5c72111bac8e4b820e4310a40105a8b0bd78b8f1c36c9176f9ac7ddf8c7b4300e9208b45711a129ab0531dd579f9a52964
7
+ data.tar.gz: d446efb23252acee7ea453361d402089b87c56450e20ed7e45b1aab2cd0381bff442ed51ea7e2a52a544c39f3117795ad17ac2208dc12514f211d12ba150bb2c
data/.rubocop.yml CHANGED
@@ -2,8 +2,6 @@
2
2
  plugins:
3
3
  - rubocop-performance
4
4
  - rubocop-rake
5
-
6
- require:
7
5
  - rubocop-capybara
8
6
  - rubocop-factory_bot
9
7
  - rubocop-rspec
@@ -27,21 +25,14 @@ Style/StringLiteralsInInterpolation:
27
25
 
28
26
  Style/HashSyntax:
29
27
  EnforcedShorthandSyntax: always
30
- # This is not rails application.
31
- # Rails/Blank:
32
- # Enabled: false
33
-
34
- # Rails/Present:
35
- # Enabled: false
36
-
37
- # Rails/TimeZone:
38
- # Enabled: false
39
28
 
40
29
  Lint/ConstantDefinitionInBlock:
41
30
  Enabled: false
42
31
 
43
32
  Metrics/MethodLength:
44
33
  Max: 15
34
+ Exclude:
35
+ - 'lib/llm_conductor/prompts.rb'
45
36
 
46
37
  RSpec/ExampleLength:
47
38
  Enabled: false
@@ -67,7 +58,7 @@ RSpec/MultipleDescribes:
67
58
  RSpec/SpecFilePathFormat:
68
59
  Enabled: false
69
60
 
70
- RSpec/FilePath:
61
+ RSpec/SpecFilePathSuffix:
71
62
  Enabled: false
72
63
 
73
64
  RSpec/UnspecifiedException:
@@ -94,6 +85,19 @@ Metrics/BlockLength:
94
85
  Exclude:
95
86
  - '*.gemspec'
96
87
 
88
+ # Prompt template methods naturally have high complexity due to conditional string building
89
+ Metrics/AbcSize:
90
+ Exclude:
91
+ - 'lib/llm_conductor/prompts.rb'
92
+
93
+ Metrics/CyclomaticComplexity:
94
+ Exclude:
95
+ - 'lib/llm_conductor/prompts.rb'
96
+
97
+ Metrics/PerceivedComplexity:
98
+ Exclude:
99
+ - 'lib/llm_conductor/prompts.rb'
100
+
97
101
  Layout/LineLength:
98
102
  Max: 120
99
103
 
data/README.md CHANGED
@@ -52,14 +52,18 @@ puts response.estimated_cost # Cost in USD
52
52
  ### 2. Template-Based Generation
53
53
 
54
54
  ```ruby
55
- # Use built-in templates with structured data
55
+ # Use built-in text summarization template
56
56
  response = LlmConductor.generate(
57
57
  model: 'gpt-5-mini',
58
- type: :summarize_description,
58
+ type: :summarize_text,
59
59
  data: {
60
- name: 'Ekohe',
61
- domain_name: 'ekohe.com',
62
- description: 'An AI company specializing in...'
60
+ text: 'Ekohe (ee-koh-hee) means "boundless possibility." Our way is to make AI practical, achievable, and most importantly, useful for you — and we prove it every day. With almost 16 years of wins under our belt, a market-leading 24-hr design & development cycle, and 5 offices in the most vibrant cities in the world, we surf the seas of innovation. We create efficient, elegant, and scalable digital products — delivering the right interactive solutions to achieve your audience and business goals. We help you transform. We break new ground across the globe — from AI and ML automation that drives the enterprise, to innovative customer experiences and mobile apps for startups. Our special sauce is the care, curiosity, and dedication we offer to solve for your needs. We focus on your success and deliver the most impactful experiences in the most efficient manner. Our clients tell us we partner with them in a trusted and capable way, driving the right design and technical choices.',
61
+ max_length: '20 words',
62
+ style: 'professional and engaging',
63
+ focus_areas: ['core business', 'expertise', 'target market'],
64
+ audience: 'potential investors',
65
+ include_key_points: true,
66
+ output_format: 'paragraph'
63
67
  }
64
68
  )
65
69
 
@@ -67,7 +71,7 @@ response = LlmConductor.generate(
67
71
  if response.success?
68
72
  puts "Generated: #{response.output}"
69
73
  puts "Tokens: #{response.total_tokens}"
70
- puts "Cost: $#{response.estimated_cost}"
74
+ puts "Cost: $#{response.estimated_cost || 'N/A (free model)'}"
71
75
  else
72
76
  puts "Error: #{response.metadata[:error]}"
73
77
  end
@@ -143,20 +147,6 @@ response = LlmConductor.generate(
143
147
  )
144
148
  ```
145
149
 
146
- **Supported Claude Models:**
147
- - `claude-3-5-sonnet-20241022` (Latest Claude 3.5 Sonnet)
148
- - `claude-3-5-haiku-20241022` (Claude 3.5 Haiku)
149
- - `claude-3-opus-20240229` (Claude 3 Opus)
150
- - `claude-3-sonnet-20240229` (Claude 3 Sonnet)
151
- - `claude-3-haiku-20240307` (Claude 3 Haiku)
152
-
153
- **Why Choose Claude?**
154
- - **Superior Reasoning**: Excellent for complex analysis and problem-solving
155
- - **Code Generation**: Outstanding performance for programming tasks
156
- - **Long Context**: Support for large documents and conversations
157
- - **Safety**: Built with safety and helpfulness in mind
158
- - **Cost Effective**: Competitive pricing for high-quality outputs
159
-
160
150
  ### Google Gemini (Automatic for Gemini models)
161
151
  ```ruby
162
152
  response = LlmConductor.generate(
@@ -172,18 +162,6 @@ response = LlmConductor.generate(
172
162
  )
173
163
  ```
174
164
 
175
- **Supported Gemini Models:**
176
- - `gemini-2.5-flash` (Latest Gemini 2.5 Flash)
177
- - `gemini-2.5-flash` (Gemini 2.5 Flash)
178
- - `gemini-2.0-flash` (Gemini 2.0 Flash)
179
-
180
- **Why Choose Gemini?**
181
- - **Multimodal**: Native support for text, images, and other modalities
182
- - **Long Context**: Massive context windows for large documents
183
- - **Fast Performance**: Optimized for speed and efficiency
184
- - **Google Integration**: Seamless integration with Google services
185
- - **Competitive Pricing**: Cost-effective for high-volume usage
186
-
187
165
  ### Ollama (Default for non-GPT/Claude/Gemini models)
188
166
  ```ruby
189
167
  response = LlmConductor.generate(
@@ -1,124 +1,140 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LlmConductor
4
- # Collection of pre-built prompt templates for common LLM tasks including
5
- # content analysis, link extraction, and data summarization.
4
+ # Collection of general-purpose prompt templates for common LLM tasks
6
5
  module Prompts
7
- def prompt_featured_links(data)
6
+ # General prompt for extracting links from HTML content
7
+ # More flexible and applicable to various use cases
8
+ def prompt_extract_links(data)
9
+ criteria = data[:criteria] || 'relevant and useful'
10
+ max_links = data[:max_links] || 10
11
+ link_types = data[:link_types] || %w[navigation content footer]
12
+
8
13
  <<~PROMPT
9
- You are an AI assistant tasked with analyzing a webpage's HTML content to extract the most valuable links. Your goal is to identify links related to features, products, solutions, pricing, and social media profiles, prioritizing those from the same domain as the current page. Here are your instructions:
14
+ Analyze the provided HTML content and extract links based on the specified criteria.
15
+
16
+ HTML Content:
17
+ #{data[:html_content] || data[:htmls]}
18
+
19
+ Extraction Criteria: #{criteria}
20
+ Maximum Links: #{max_links}
21
+ Link Types to Consider: #{link_types.join(', ')}
10
22
 
11
- - You will be provided with the HTML content of the current page in the following format:
12
- <page_html>
13
- #{data[:htmls]}
14
- </page_html>
23
+ #{"Domain Filter: Only include links from domain #{data[:domain_filter]}" if data[:domain_filter]}
15
24
 
16
- - Parse the HTML content and extract all hyperlinks (a href attributes). Pay special attention to links in the navigation menu, footer, and main content areas.
25
+ Instructions:
26
+ 1. Parse the HTML content and identify all hyperlinks
27
+ 2. Filter links based on the provided criteria
28
+ 3. Prioritize links from specified areas: #{link_types.join(', ')}
29
+ 4. Return up to #{max_links} most relevant links
30
+ #{if data[:format] == :json
31
+ '5. Format output as a JSON array of URLs'
32
+ else
33
+ '5. Format output as a newline-separated list of URLs'
34
+ end}
17
35
 
18
- - Filter and prioritize the extracted links based on the following criteria:
19
- a. The link must be from the same domain as the current URL.
20
- b. Prioritize links containing keywords such as "features", "products", "solutions", "pricing", "about", "contact", or similar variations.
21
- c. Include social media profile links (e.g., LinkedIn, Instagram, Twitter, Facebook) if available.
22
- d. Exclude links to login pages, search pages, or other utility pages.
36
+ Provide only the links without additional commentary.
37
+ PROMPT
38
+ end
23
39
 
24
- - Select the top 3 most valuable links based on the above criteria.
40
+ # General prompt for content analysis and data extraction
41
+ # Flexible template for various content analysis tasks
42
+ def prompt_analyze_content(data)
43
+ content_type = data[:content_type] || 'webpage content'
44
+ analysis_fields = data[:fields] || %w[summary key_points entities]
45
+ output_format = data[:output_format] || 'structured text'
25
46
 
26
- - Format your output as a JSON array of strings, where each string is a full URL. Use the following format:
27
- <output_format>
28
- ["https://example.com/about-us", "https://example.com/products", "https://example.com/services"]
29
- </output_format>
47
+ <<~PROMPT
48
+ Analyze the provided #{content_type} and extract the requested information.
30
49
 
31
- - The links must be the same domain of following
32
- <domain>
33
- #{data[:current_url]}
34
- </domain>
50
+ Content:
51
+ #{data[:content] || data[:htmls] || data[:text]}
35
52
 
36
- If fewer than 3 relevant links are found, include only the available links in the output array.
53
+ Analysis Fields:
54
+ #{analysis_fields.map { |field| "- #{field}" }.join("\n")}
37
55
 
38
- Remember to use the full URL for each link, including the domain name. If you encounter relative URLs, combine them with the domain from the current URL to create absolute URLs.
56
+ #{"Additional Instructions:\n#{data[:instructions]}" if data[:instructions]}
39
57
 
40
- Provide your final output without any additional explanation or commentary.
58
+ #{if output_format == 'json'
59
+ json_structure = analysis_fields.map { |field| " \"#{field}\": \"value or array\"" }.join(",\n")
60
+ "Output Format: JSON with the following structure:\n{\n#{json_structure}\n}"
61
+ else
62
+ "Output Format: #{output_format}"
63
+ end}
64
+
65
+ #{"Constraints:\n#{data[:constraints]}" if data[:constraints]}
66
+
67
+ Provide a comprehensive analysis focusing on the requested fields.
41
68
  PROMPT
42
69
  end
43
70
 
44
- def prompt_summarize_htmls(data)
71
+ # General prompt for text summarization
72
+ # Applicable to various types of text content
73
+ def prompt_summarize_text(data)
74
+ max_length = data[:max_length] || '200 words'
75
+ focus_areas = data[:focus_areas] || []
76
+ style = data[:style] || 'concise and informative'
77
+
45
78
  <<~PROMPT
46
- Extract useful information from the webpage including a domain, detailed description of what the company does, founding year, country, business model, product description and features, customers and partners, development stage, and social media links. output will be json
47
-
48
- You are tasked with extracting useful information about a company from a given webpage content. Your goal is to analyze the content and extract specific details about the company, its products, and its operations.
49
-
50
- You will be provided with raw HTML content in the following format:
51
-
52
- <html_content>
53
- #{data[:htmls]}
54
- </html_content>
55
-
56
- Carefully read through the webpage content and extract the following information about the company:
57
-
58
- - Name(field name): The company's name
59
- - Domain name(field domain_name): The company's domain
60
- - Description(field description): A comprehensive explanation of what the company does
61
- - Country(field country): The company's country
62
- - Region(field region): The company's region
63
- - Location(field location): The company's location
64
- - Founding on(field founded_on): Which year the company was established
65
- - Business model(field business_model): How the company generates revenue
66
- - Product description(product_description): A brief overview of the company's main product(s) or service(s)
67
- - Product features(product_features): Key features or capabilities of the product(s) or service(s)
68
- - Customers and partners(field customers_and_partners): Notable clients or business partners
69
- - Development stage(field development_stage): The current phase of the company (e.g., startup, growth, established)
70
- - Social media links(field social_media_links): URLs to the company's social media profiles
71
- - instagram_url
72
- - linkedin_url
73
- - twitter_url
74
-
75
- If any of the above information is not available in the webpage content, use "Not available" as the value for that field.
76
-
77
- Present your findings in a JSON format. Here's an example of the expected structure:
78
-
79
- <output_format>
80
- {
81
- "name": "AI-powered customer service",
82
- "domain_name": "example.com",
83
- "description": "XYZ Company develops AI chatbots that help businesses automate customer support...",
84
- "founding_on": 2018,
85
- "country": "United States",
86
- "Region": "SA",
87
- "Location": "SFO",
88
- "business_model": "SaaS subscription",
89
- "product_description": "AI-powered chatbot platform for customer service automation",
90
- "product_features": ["Natural language processing", "Multi-language support", "Integration with CRM systems"],
91
- "customers_and_partners": ["ABC Corp", "123 Industries", "Big Tech Co."],
92
- "development_stage": "Growth",
93
- "social_media_links": {
94
- "linkedin_url": "https://www.linkedin.com/company/xyzcompany",
95
- "twitter_url": "https://twitter.com/xyzcompany",
96
- "instagram_url": "https://www.instagram.com/xyzcompany"
97
- }
98
- }
99
- </output_format>
100
-
101
- Remember to use only the information provided in the webpage content. Do not include any external information or make assumptions beyond what is explicitly stated or strongly implied in the given content.
102
-
103
- Present your final output in JSON format, enclosed within <json_output> tags.
79
+ Summarize the following text content.
80
+
81
+ Text:
82
+ #{data[:text] || data[:content] || data[:description]}
83
+
84
+ Summary Requirements:
85
+ - Maximum Length: #{max_length}
86
+ - Style: #{style}
87
+ #{"- Focus Areas: #{focus_areas.join(', ')}" if focus_areas.any?}
88
+ #{"- Target Audience: #{data[:audience]}" if data[:audience]}
89
+
90
+ #{'Include key points and main themes.' if data[:include_key_points]}
91
+
92
+ #{if data[:output_format] == 'bullet_points'
93
+ 'Format as bullet points.'
94
+ elsif data[:output_format] == 'paragraph'
95
+ 'Format as a single paragraph.'
96
+ end}
97
+
98
+ Provide a clear and accurate summary.
104
99
  PROMPT
105
100
  end
106
101
 
107
- def prompt_summarize_description(data)
102
+ # General prompt for data classification and categorization
103
+ # Useful for various classification tasks
104
+ def prompt_classify_content(data)
105
+ categories = data[:categories] || []
106
+ classification_type = data[:classification_type] || 'content'
107
+ confidence_scores = data[:include_confidence] || false
108
+
108
109
  <<~PROMPT
109
- Given the company's name, domain, description, and a list of industry-related keywords,
110
- please summarize the company's core business and identify the three most relevant industries.
111
- Highlight the company's unique value proposition, its primary market focus,
112
- and any distinguishing features that set it apart within the identified industries.
113
- Be as objective as possible.
114
-
115
- Name: #{data[:name]}
116
- Domain Name: #{data[:domain_name]}
117
- Industry: #{data[:industries]}
118
- Description: #{data[:description]}
110
+ Classify the provided #{classification_type} into the most appropriate category.
111
+
112
+ Content to Classify:
113
+ #{data[:content] || data[:text] || data[:description]}
114
+
115
+ Available Categories:
116
+ #{categories.map.with_index(1) { |cat, i| "#{i}. #{cat}" }.join("\n")}
117
+
118
+ #{"Classification Criteria:\n#{data[:classification_criteria]}" if data[:classification_criteria]}
119
+
120
+ #{if confidence_scores
121
+ 'Output Format: JSON with category and confidence score (0-1)'
122
+ else
123
+ 'Output Format: Return the most appropriate category name'
124
+ end}
125
+
126
+ #{if data[:multiple_categories]
127
+ "Note: Multiple categories may apply - select up to #{data[:max_categories] || 3} most relevant."
128
+ else
129
+ 'Note: Select only the single most appropriate category.'
130
+ end}
131
+
132
+ Provide your classification based on the content analysis.
119
133
  PROMPT
120
134
  end
121
135
 
136
+ # Flexible custom prompt template
137
+ # Allows for dynamic prompt creation with variable substitution
122
138
  def prompt_custom(data)
123
139
  template = data.fetch(:template)
124
140
  template % data
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LlmConductor
4
- VERSION = '0.1.1'
4
+ VERSION = '1.0.0'
5
5
  end
data/lib/llm_conductor.rb CHANGED
@@ -74,9 +74,10 @@ module LlmConductor
74
74
 
75
75
  # List of supported prompt types
76
76
  SUPPORTED_PROMPT_TYPES = %i[
77
- featured_links
78
- summarize_htmls
79
- summarize_description
77
+ extract_links
78
+ analyze_content
79
+ summarize_text
80
+ classify_content
80
81
  custom
81
82
  ].freeze
82
83
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: llm_conductor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Zheng
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-09-25 00:00:00.000000000 Z
10
+ date: 2025-09-26 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activesupport