agent99 0.0.4 → 0.0.5
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 +4 -4
- data/A2A_SPEC-dev.md +1829 -0
- data/CHANGELOG.md +31 -0
- data/COMMITS.md +196 -0
- data/DOCS.md +96 -0
- data/README.md +200 -78
- data/Rakefile +62 -0
- data/docs/AI/htm.md +215 -0
- data/docs/AI/htm.rb +141 -0
- data/docs/AI/htm_demo.db +0 -0
- data/docs/AI/notes_on_htm_implementation.md +1319 -0
- data/docs/AI/some_code.rb +692 -0
- data/docs/advanced-topics/a2a-protocol.md +13 -0
- data/docs/{control_actions.md → advanced-topics/control-actions.md} +2 -0
- data/docs/advanced-topics/model-context-protocol.md +4 -0
- data/docs/advanced-topics/multi-agent-processing.md +674 -0
- data/docs/agent-development/request-response-handling.md +512 -0
- data/docs/api-reference/agent99-base.md +463 -0
- data/docs/api-reference/message-clients.md +495 -0
- data/docs/api-reference/registry-client.md +470 -0
- data/docs/api-reference/schemas.md +518 -0
- data/docs/assets/css/custom.css +27 -0
- data/docs/assets/images/agent-lifecycle.svg +73 -0
- data/docs/assets/images/agent-registry-process.svg +86 -0
- data/docs/assets/images/agent-registry-processes.svg +114 -0
- data/docs/assets/images/agent-types-overview.svg +51 -0
- data/docs/assets/images/agent99-architecture.svg +85 -0
- data/docs/assets/images/agent99_logo.png +0 -0
- data/docs/assets/images/control-actions-state.svg +83 -0
- data/docs/assets/images/knowledge-graph.svg +77 -0
- data/docs/assets/images/message-processing-flow.svg +148 -0
- data/docs/assets/images/multi-agent-system.svg +66 -0
- data/docs/assets/images/proxy-pattern-sequence.svg +48 -0
- data/docs/assets/images/request-flow.svg +97 -0
- data/docs/assets/images/request-processing-lifecycle.svg +50 -0
- data/docs/assets/images/request-response-sequence.svg +39 -0
- data/docs/{agent_lifecycle.md → core-concepts/agent-lifecycle.md} +2 -0
- data/docs/core-concepts/agent-types.md +255 -0
- data/docs/{architecture.md → core-concepts/architecture.md} +5 -5
- data/docs/{what_is_an_agent.md → core-concepts/what-is-an-agent.md} +1 -1
- data/docs/diagrams/message-flow-sequence.svg +198 -0
- data/docs/diagrams/p2p-network-topology.svg +181 -0
- data/docs/diagrams/smart-transport-routing.svg +165 -0
- data/docs/diagrams/three-layer-architecture.svg +77 -0
- data/docs/diagrams/transport-extension-api.svg +309 -0
- data/docs/diagrams/transport-extension-architecture.svg +234 -0
- data/docs/diagrams/transport-selection-flowchart.svg +264 -0
- data/docs/examples/advanced-examples.md +951 -0
- data/docs/examples/basic-examples.md +268 -0
- data/docs/{agent_registry_processes.md → framework-components/agent-registry.md} +1 -1
- data/docs/{message_processing.md → framework-components/message-processing.md} +3 -1
- data/docs/getting-started/basic-example.md +306 -0
- data/docs/getting-started/installation.md +160 -0
- data/docs/getting-started/overview.md +64 -0
- data/docs/getting-started/quick-start.md +179 -0
- data/docs/index.md +97 -0
- data/examples/DEMO.md +148 -0
- data/examples/README.md +50 -0
- data/examples/bad_agent.rb +32 -0
- data/examples/registry.rb +0 -8
- data/examples/run_demo.rb +433 -0
- data/lib/agent99/amqp_message_client.rb +2 -2
- data/lib/agent99/base.rb +1 -1
- data/lib/agent99/message_processing.rb +6 -12
- data/lib/agent99/registry_client.rb +4 -1
- data/lib/agent99/version.rb +1 -1
- data/lib/agent99.rb +1 -1
- data/mkdocs.yml +195 -0
- data/p2p_plan.md +533 -0
- data/p2p_roadmap.md +299 -0
- data/registry_plan.md +1818 -0
- metadata +89 -32
- data/docs/README.md +0 -57
- data/docs/diagrams/agent_registry_processes.dot +0 -42
- data/docs/diagrams/agent_registry_processes.png +0 -0
- data/docs/diagrams/high_level_architecture.dot +0 -26
- data/docs/diagrams/high_level_architecture.png +0 -0
- data/docs/diagrams/request_flow.dot +0 -42
- data/docs/diagrams/request_flow.png +0 -0
- /data/docs/{advanced_features.md → advanced-topics/advanced-features.md} +0 -0
- /data/docs/{extending_the_framework.md → advanced-topics/extending-the-framework.md} +0 -0
- /data/docs/{custom_agent_implementation.md → agent-development/custom-agent-implementation.md} +0 -0
- /data/docs/{error_handling_and_logging.md → agent-development/error-handling-and-logging.md} +0 -0
- /data/docs/{schema_definition.md → agent-development/schema-definition.md} +0 -0
- /data/docs/{api_reference.md → api-reference/overview.md} +0 -0
- /data/docs/{agent_discovery.md → framework-components/agent-discovery.md} +0 -0
- /data/docs/{messaging_system.md → framework-components/messaging-system.md} +0 -0
- /data/docs/{breaking_change_v0.0.4.md → operations/breaking-changes.md} +0 -0
- /data/docs/{configuration.md → operations/configuration.md} +0 -0
- /data/docs/{preformance_considerations.md → operations/performance-considerations.md} +0 -0
- /data/docs/{security.md → operations/security.md} +0 -0
- /data/docs/{troubleshooting.md → operations/troubleshooting.md} +0 -0
@@ -0,0 +1,692 @@
|
|
1
|
+
# some_code.rb
|
2
|
+
# snippets written by the robot
|
3
|
+
############################################
|
4
|
+
class KnowledgeNode
|
5
|
+
attr_reader :id, :content, :detail_level
|
6
|
+
|
7
|
+
def initialize(id:, content:, detail_level:)
|
8
|
+
@id = id
|
9
|
+
@content = content
|
10
|
+
@detail_level = detail_level
|
11
|
+
@connections = {
|
12
|
+
more_general: [],
|
13
|
+
more_specific: [],
|
14
|
+
related: [],
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_connection(node:, relationship:)
|
19
|
+
@connections[relationship] << node
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class KnowledgeGraph
|
24
|
+
def initialize
|
25
|
+
@nodes = {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_node(node:)
|
29
|
+
@nodes[node.id] = node
|
30
|
+
end
|
31
|
+
|
32
|
+
def connect_nodes(from_id:, to_id:, relationship:)
|
33
|
+
from_node = @nodes[from_id]
|
34
|
+
to_node = @nodes[to_id]
|
35
|
+
from_node.add_connection(node: to_node, relationship: relationship)
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_more_specific(node_id:)
|
39
|
+
@nodes[node_id].connections[:more_specific]
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_more_general(node_id:)
|
43
|
+
@nodes[node_id].connections[:more_general]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
############################################
|
48
|
+
require "neo4j"
|
49
|
+
|
50
|
+
class Concept
|
51
|
+
include Neo4j::ActiveNode
|
52
|
+
property :name, type: String
|
53
|
+
property :detail_level, type: Integer
|
54
|
+
|
55
|
+
has_many :out, :more_specific, type: :SPECIALIZES, model_class: "Concept"
|
56
|
+
has_many :in, :more_general, type: :SPECIALIZES, model_class: "Concept"
|
57
|
+
end
|
58
|
+
|
59
|
+
# Create nodes
|
60
|
+
general = Concept.create(name: "Science", detail_level: 1)
|
61
|
+
specific = Concept.create(name: "Physics", detail_level: 2)
|
62
|
+
|
63
|
+
# Create relationship
|
64
|
+
general.more_specific << specific
|
65
|
+
|
66
|
+
############################################
|
67
|
+
require "graphviz"
|
68
|
+
|
69
|
+
graph = GraphViz.new(:G, type: :digraph)
|
70
|
+
|
71
|
+
node1 = graph.add_nodes("Science")
|
72
|
+
node2 = graph.add_nodes("Physics")
|
73
|
+
|
74
|
+
graph.add_edges(node1, node2)
|
75
|
+
|
76
|
+
# See knowledge graph visualization at:
|
77
|
+
# docs/assets/images/knowledge-graph.svg
|
78
|
+
# graph.output(png: "knowledge_graph.png")
|
79
|
+
|
80
|
+
############################################
|
81
|
+
require "rgl/adjacency"
|
82
|
+
require "rgl/dot"
|
83
|
+
|
84
|
+
graph = RGL::DirectedAdjacencyGraph.new
|
85
|
+
|
86
|
+
graph.add_edge("Science", "Physics")
|
87
|
+
graph.add_edge("Physics", "Quantum Mechanics")
|
88
|
+
|
89
|
+
graph.write_to_graphic_file("jpg")
|
90
|
+
|
91
|
+
############################################
|
92
|
+
require "orientdb"
|
93
|
+
|
94
|
+
database = OrientDB::Database.new(url: "remote:localhost/knowledge_graph")
|
95
|
+
|
96
|
+
database.create_vertex_type("Concept")
|
97
|
+
|
98
|
+
science = database.create_vertex("Concept", name: "Science", detail_level: 1)
|
99
|
+
physics = database.create_vertex("Concept", name: "Physics", detail_level: 2)
|
100
|
+
|
101
|
+
database.create_edge("Specializes", science, physics)
|
102
|
+
|
103
|
+
############################################
|
104
|
+
class KnowledgeNode
|
105
|
+
attr_reader :id, :content, :detail_level, :last_accessed
|
106
|
+
|
107
|
+
def initialize(id:, content:, detail_level:)
|
108
|
+
@id = id
|
109
|
+
@content = content
|
110
|
+
@detail_level = detail_level
|
111
|
+
@last_accessed = Time.now
|
112
|
+
@connections = {
|
113
|
+
more_general: [],
|
114
|
+
more_specific: [],
|
115
|
+
related: [],
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
def access
|
120
|
+
@last_accessed = Time.now
|
121
|
+
end
|
122
|
+
|
123
|
+
def forgettable?(threshold)
|
124
|
+
Time.now - @last_accessed > threshold * (1.0 / @detail_level)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class TemporalKnowledgeGraph
|
129
|
+
def initialize(forget_threshold: 30 * 24 * 60 * 60) # 30 days in seconds
|
130
|
+
@nodes = {}
|
131
|
+
@forget_threshold = forget_threshold
|
132
|
+
end
|
133
|
+
|
134
|
+
def add_node(node:)
|
135
|
+
@nodes[node.id] = node
|
136
|
+
end
|
137
|
+
|
138
|
+
def access_node(id:)
|
139
|
+
node = @nodes[id]
|
140
|
+
node.access if node
|
141
|
+
node
|
142
|
+
end
|
143
|
+
|
144
|
+
def forget_old_nodes
|
145
|
+
@nodes.delete_if do |id, node|
|
146
|
+
node.forgettable?(@forget_threshold)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def connect_nodes(from_id:, to_id:, relationship:)
|
151
|
+
from_node = @nodes[from_id]
|
152
|
+
to_node = @nodes[to_id]
|
153
|
+
from_node.connections[relationship] << to_node if from_node && to_node
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Usage
|
158
|
+
graph = TemporalKnowledgeGraph.new(forget_threshold: 60 * 60 * 24) # 1 day
|
159
|
+
|
160
|
+
node1 = KnowledgeNode.new(id: 1, content: "Science", detail_level: 1)
|
161
|
+
node2 = KnowledgeNode.new(id: 2, content: "Physics", detail_level: 2)
|
162
|
+
node3 = KnowledgeNode.new(id: 3, content: "Quantum Entanglement", detail_level: 3)
|
163
|
+
|
164
|
+
graph.add_node(node: node1)
|
165
|
+
graph.add_node(node: node2)
|
166
|
+
graph.add_node(node: node3)
|
167
|
+
|
168
|
+
graph.connect_nodes(from_id: 1, to_id: 2, relationship: :more_specific)
|
169
|
+
graph.connect_nodes(from_id: 2, to_id: 3, relationship: :more_specific)
|
170
|
+
|
171
|
+
# Simulate passage of time and node access
|
172
|
+
sleep(2)
|
173
|
+
graph.access_node(id: 1)
|
174
|
+
graph.access_node(id: 2)
|
175
|
+
|
176
|
+
sleep(2)
|
177
|
+
graph.forget_old_nodes
|
178
|
+
# At this point, node3 might be forgotten, while node1 and node2 are retained
|
179
|
+
|
180
|
+
|
181
|
+
############################################
|
182
|
+
require "set"
|
183
|
+
|
184
|
+
class HTMNode
|
185
|
+
attr_reader :id, :content, :detail_level, :last_accessed, :access_count
|
186
|
+
|
187
|
+
def initialize(id:, content:, detail_level:)
|
188
|
+
@id = id
|
189
|
+
@content = content
|
190
|
+
@detail_level = detail_level
|
191
|
+
@last_accessed = Time.now
|
192
|
+
@access_count = 0
|
193
|
+
@connections = Set.new
|
194
|
+
end
|
195
|
+
|
196
|
+
def access
|
197
|
+
@last_accessed = Time.now
|
198
|
+
@access_count += 1
|
199
|
+
end
|
200
|
+
|
201
|
+
def add_connection(node)
|
202
|
+
@connections.add(node)
|
203
|
+
end
|
204
|
+
|
205
|
+
def relevance_score(current_time)
|
206
|
+
time_factor = 1.0 / (current_time - @last_accessed)
|
207
|
+
detail_factor = 1.0 / @detail_level
|
208
|
+
access_factor = Math.log(@access_count + 1)
|
209
|
+
time_factor * detail_factor * access_factor
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class HTMRAG
|
214
|
+
def initialize(forget_threshold: 30 * 24 * 60 * 60) # 30 days in seconds
|
215
|
+
@nodes = {}
|
216
|
+
@forget_threshold = forget_threshold
|
217
|
+
end
|
218
|
+
|
219
|
+
def add_node(node)
|
220
|
+
@nodes[node.id] = node
|
221
|
+
end
|
222
|
+
|
223
|
+
def connect_nodes(from_id, to_id)
|
224
|
+
@nodes[from_id].add_connection(@nodes[to_id])
|
225
|
+
end
|
226
|
+
|
227
|
+
def forget_old_nodes
|
228
|
+
current_time = Time.now
|
229
|
+
@nodes.delete_if do |_, node|
|
230
|
+
current_time - node.last_accessed > @forget_threshold
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def retrieve_context(query, max_tokens: 1000)
|
235
|
+
relevant_nodes = find_relevant_nodes(query)
|
236
|
+
construct_context(relevant_nodes, max_tokens)
|
237
|
+
end
|
238
|
+
|
239
|
+
private
|
240
|
+
|
241
|
+
def find_relevant_nodes(query)
|
242
|
+
# This is a placeholder for semantic search
|
243
|
+
# In a real implementation, you'd use embeddings or other NLP techniques
|
244
|
+
@nodes.values.sort_by { |node| -node.relevance_score(Time.now) }
|
245
|
+
end
|
246
|
+
|
247
|
+
def construct_context(nodes, max_tokens)
|
248
|
+
context = ""
|
249
|
+
token_count = 0
|
250
|
+
|
251
|
+
nodes.each do |node|
|
252
|
+
break if token_count >= max_tokens
|
253
|
+
|
254
|
+
node_content = node.content
|
255
|
+
node_tokens = node_content.split.size # Simple tokenization
|
256
|
+
|
257
|
+
if token_count + node_tokens <= max_tokens
|
258
|
+
context += node_content + " "
|
259
|
+
token_count += node_tokens
|
260
|
+
node.access
|
261
|
+
else
|
262
|
+
remaining_tokens = max_tokens - token_count
|
263
|
+
truncated_content = node_content.split[0...remaining_tokens].join(" ")
|
264
|
+
context += truncated_content + " "
|
265
|
+
break
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
context.strip
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
# Usage example
|
274
|
+
rag = HTMRAG.new
|
275
|
+
|
276
|
+
node1 = HTMNode.new(id: 1, content: "AI is a broad field of computer science.", detail_level: 1)
|
277
|
+
node2 = HTMNode.new(id: 2, content: "Machine Learning is a subset of AI focused on data-driven
|
278
|
+
algorithms.", detail_level: 2)
|
279
|
+
node3 = HTMNode.new(id: 3, content: "Neural networks are a type of machine learning model
|
280
|
+
inspired by biological neurons.", detail_level: 3)
|
281
|
+
|
282
|
+
rag.add_node(node1)
|
283
|
+
rag.add_node(node2)
|
284
|
+
rag.add_node(node3)
|
285
|
+
|
286
|
+
rag.connect_nodes(1, 2)
|
287
|
+
rag.connect_nodes(2, 3)
|
288
|
+
|
289
|
+
context = rag.retrieve_context("What is AI?", max_tokens: 50)
|
290
|
+
puts context
|
291
|
+
|
292
|
+
|
293
|
+
############################################
|
294
|
+
class Proposition
|
295
|
+
attr_reader :id, :content
|
296
|
+
attr_accessor :next, :related
|
297
|
+
|
298
|
+
def initialize(id:, content:)
|
299
|
+
@id = id
|
300
|
+
@content = content
|
301
|
+
@next = nil
|
302
|
+
@related = []
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
class PropositionGraph
|
307
|
+
attr_reader :propositions
|
308
|
+
|
309
|
+
def initialize
|
310
|
+
@propositions = {}
|
311
|
+
end
|
312
|
+
|
313
|
+
def add_proposition(prop)
|
314
|
+
@propositions[prop.id] = prop
|
315
|
+
end
|
316
|
+
|
317
|
+
def connect(from_id:, to_id:, relationship: :next)
|
318
|
+
from_prop = @propositions[from_id]
|
319
|
+
to_prop = @propositions[to_id]
|
320
|
+
if relationship == :next
|
321
|
+
from_prop.next = to_prop
|
322
|
+
else
|
323
|
+
from_prop.related << to_prop
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
def similarity_score(other_graph)
|
328
|
+
sequence_similarity = calculate_sequence_similarity(other_graph)
|
329
|
+
structure_similarity = calculate_structure_similarity(other_graph)
|
330
|
+
(sequence_similarity + structure_similarity) / 2.0
|
331
|
+
end
|
332
|
+
|
333
|
+
private
|
334
|
+
|
335
|
+
def calculate_sequence_similarity(other_graph)
|
336
|
+
# Implement sequence comparison logic here
|
337
|
+
# This could involve comparing the 'next' chains of both graphs
|
338
|
+
# Return a score between 0 and 1
|
339
|
+
end
|
340
|
+
|
341
|
+
def calculate_structure_similarity(other_graph)
|
342
|
+
# Implement structure comparison logic here
|
343
|
+
# This could involve comparing the 'related' connections of both graphs
|
344
|
+
# Return a score between 0 and 1
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
class GraphBasedRAG
|
349
|
+
def initialize
|
350
|
+
@stored_graphs = []
|
351
|
+
end
|
352
|
+
|
353
|
+
def add_graph(graph)
|
354
|
+
@stored_graphs << graph
|
355
|
+
end
|
356
|
+
|
357
|
+
def retrieve_context(prompt_graph, top_n: 3)
|
358
|
+
scored_graphs = @stored_graphs.map do |graph|
|
359
|
+
{
|
360
|
+
graph: graph,
|
361
|
+
score: graph.similarity_score(prompt_graph),
|
362
|
+
}
|
363
|
+
end
|
364
|
+
|
365
|
+
top_graphs = scored_graphs.sort_by { |g| -g[:score] }.take(top_n)
|
366
|
+
construct_context(top_graphs)
|
367
|
+
end
|
368
|
+
|
369
|
+
private
|
370
|
+
|
371
|
+
def construct_context(top_graphs)
|
372
|
+
# Implement logic to construct context from top graphs
|
373
|
+
# This could involve extracting key propositions or summarizing the graphs
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
# Usage example
|
378
|
+
rag = GraphBasedRAG.new
|
379
|
+
|
380
|
+
# Create and add some stored graphs
|
381
|
+
graph1 = PropositionGraph.new
|
382
|
+
prop1 = Proposition.new(id: 1, content: "AI is a field of computer science")
|
383
|
+
prop2 = Proposition.new(id: 2, content: "Machine Learning is a subset of AI")
|
384
|
+
graph1.add_proposition(prop1)
|
385
|
+
graph1.add_proposition(prop2)
|
386
|
+
graph1.connect(from_id: 1, to_id: 2)
|
387
|
+
rag.add_graph(graph1)
|
388
|
+
|
389
|
+
# ... Add more graphs ...
|
390
|
+
|
391
|
+
# Create a graph from the prompt
|
392
|
+
prompt_graph = PropositionGraph.new
|
393
|
+
prompt_prop1 = Proposition.new(id: 1, content: "What is AI")
|
394
|
+
prompt_prop2 = Proposition.new(id: 2, content: "How does it relate to Machine Learning")
|
395
|
+
prompt_graph.add_proposition(prompt_prop1)
|
396
|
+
prompt_graph.add_proposition(prompt_prop2)
|
397
|
+
prompt_graph.connect(from_id: 1, to_id: 2)
|
398
|
+
|
399
|
+
# Retrieve context
|
400
|
+
context = rag.retrieve_context(prompt_graph)
|
401
|
+
puts context
|
402
|
+
|
403
|
+
|
404
|
+
############################################
|
405
|
+
require "pg"
|
406
|
+
|
407
|
+
class GraphDatabase
|
408
|
+
def initialize(dbname:, user:, password:)
|
409
|
+
@conn = PG.connect(dbname: dbname, user: user, password: password)
|
410
|
+
@conn.exec("CREATE EXTENSION IF NOT EXISTS age")
|
411
|
+
@conn.exec("LOAD 'age'")
|
412
|
+
@conn.exec("SET search_path = ag_catalog, \"$user\", public")
|
413
|
+
end
|
414
|
+
|
415
|
+
def create_graph(name)
|
416
|
+
@conn.exec("SELECT create_graph('#{name}')")
|
417
|
+
end
|
418
|
+
|
419
|
+
def add_vertex(graph, properties)
|
420
|
+
props = properties.map { |k, v| "#{k}: '#{v}'" }.join(", ")
|
421
|
+
@conn.exec("SELECT * FROM cypher('#{graph}', $$ CREATE (:Proposition {#{props}}) $$) as (v
|
422
|
+
agtype)")
|
423
|
+
end
|
424
|
+
|
425
|
+
def add_edge(graph, from_id, to_id, relationship)
|
426
|
+
@conn.exec("SELECT * FROM cypher('#{graph}', $$ MATCH (a), (b) WHERE id(a) = #{from_id} AND
|
427
|
+
id(b) = #{to_id} CREATE (a)-[:#{relationship}]->(b) $$) as (e agtype)")
|
428
|
+
end
|
429
|
+
|
430
|
+
def query(graph, cypher)
|
431
|
+
result = @conn.exec("SELECT * FROM cypher('#{graph}', $$ #{cypher} $$) as (result agtype)")
|
432
|
+
result.map { |row| row["result"] }
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
# Usage
|
437
|
+
db = GraphDatabase.new(dbname: "your_db", user: "your_user", password: "your_password")
|
438
|
+
db.create_graph("knowledge_graph")
|
439
|
+
db.add_vertex("knowledge_graph", { content: "AI is a field of computer science", detail_level: 1 })
|
440
|
+
db.add_vertex("knowledge_graph", { content: "Machine Learning is a subset of AI", detail_level: 2 })
|
441
|
+
db.add_edge("knowledge_graph", 0, 1, "SPECIALIZES")
|
442
|
+
|
443
|
+
result = db.query("knowledge_graph", "MATCH (p:Proposition) RETURN p")
|
444
|
+
puts result
|
445
|
+
|
446
|
+
|
447
|
+
############################################
|
448
|
+
class PropositionGraphDatabase
|
449
|
+
def initialize(dbname:, user:, password:)
|
450
|
+
@db = GraphDatabase.new(dbname: dbname, user: user, password: password)
|
451
|
+
@db.create_graph("proposition_graph")
|
452
|
+
end
|
453
|
+
|
454
|
+
def add_proposition(content:, detail_level:)
|
455
|
+
@db.add_vertex("proposition_graph", { content: content, detail_level: detail_level })
|
456
|
+
end
|
457
|
+
|
458
|
+
def connect_propositions(from_id:, to_id:, relationship: "NEXT")
|
459
|
+
@db.add_edge("proposition_graph", from_id, to_id, relationship)
|
460
|
+
end
|
461
|
+
|
462
|
+
def find_similar_graphs(prompt_graph)
|
463
|
+
# This is a simplified example. In practice, you'd need a more sophisticated
|
464
|
+
# algorithm to compare graph structures.
|
465
|
+
cypher = "" "
|
466
|
+
MATCH path = (start:Proposition)-[:NEXT*]->(end:Proposition)
|
467
|
+
WHERE NOT (end)-[:NEXT]->()
|
468
|
+
WITH path, nodes(path) AS props
|
469
|
+
RETURN path,
|
470
|
+
reduce(similarity = 0, p IN props |
|
471
|
+
similarity + CASE WHEN p.content CONTAINS '#{prompt_graph.first.content}' THEN 1 ELSE 0 END
|
472
|
+
) AS similarity_score
|
473
|
+
ORDER BY similarity_score DESC
|
474
|
+
LIMIT 5
|
475
|
+
" ""
|
476
|
+
@db.query("proposition_graph", cypher)
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
# Usage
|
481
|
+
graph_db = PropositionGraphDatabase.new(dbname: "your_db", user: "your_user", password: "your_password")
|
482
|
+
graph_db.add_proposition(content: "AI is a field of computer science", detail_level: 1)
|
483
|
+
graph_db.add_proposition(content: "Machine Learning is a subset of AI", detail_level: 2)
|
484
|
+
graph_db.connect_propositions(from_id: 0, to_id: 1)
|
485
|
+
|
486
|
+
prompt_graph = [OpenStruct.new(content: "What is AI")]
|
487
|
+
similar_graphs = graph_db.find_similar_graphs(prompt_graph)
|
488
|
+
puts similar_graphs
|
489
|
+
|
490
|
+
|
491
|
+
############################################
|
492
|
+
class PropositionGraphDatabase
|
493
|
+
def initialize(dbname:, user:, password:)
|
494
|
+
@db = GraphDatabase.new(dbname: dbname, user: user, password: password)
|
495
|
+
@db.create_graph("proposition_graph")
|
496
|
+
end
|
497
|
+
|
498
|
+
def add_proposition(content:, detail_level:)
|
499
|
+
@db.add_vertex("proposition_graph", { content: content, detail_level: detail_level })
|
500
|
+
end
|
501
|
+
|
502
|
+
def connect_propositions(from_id:, to_id:, relationship: "NEXT")
|
503
|
+
@db.add_edge("proposition_graph", from_id, to_id, relationship)
|
504
|
+
end
|
505
|
+
|
506
|
+
def find_similar_graphs(prompt_graph)
|
507
|
+
# This is a simplified example. In practice, you'd need a more sophisticated
|
508
|
+
# algorithm to compare graph structures.
|
509
|
+
cypher = "" "
|
510
|
+
MATCH path = (start:Proposition)-[:NEXT*]->(end:Proposition)
|
511
|
+
WHERE NOT (end)-[:NEXT]->()
|
512
|
+
WITH path, nodes(path) AS props
|
513
|
+
RETURN path,
|
514
|
+
reduce(similarity = 0, p IN props |
|
515
|
+
similarity + CASE WHEN p.content CONTAINS '#{prompt_graph.first.content}' THEN 1 ELSE 0 END
|
516
|
+
) AS similarity_score
|
517
|
+
ORDER BY similarity_score DESC
|
518
|
+
LIMIT 5
|
519
|
+
" ""
|
520
|
+
@db.query("proposition_graph", cypher)
|
521
|
+
end
|
522
|
+
end
|
523
|
+
|
524
|
+
# Usage
|
525
|
+
graph_db = PropositionGraphDatabase.new(dbname: "your_db", user: "your_user", password: "your_password")
|
526
|
+
graph_db.add_proposition(content: "AI is a field of computer science", detail_level: 1)
|
527
|
+
graph_db.add_proposition(content: "Machine Learning is a subset of AI", detail_level: 2)
|
528
|
+
graph_db.connect_propositions(from_id: 0, to_id: 1)
|
529
|
+
|
530
|
+
prompt_graph = [OpenStruct.new(content: "What is AI")]
|
531
|
+
similar_graphs = graph_db.find_similar_graphs(prompt_graph)
|
532
|
+
puts similar_graphs
|
533
|
+
|
534
|
+
|
535
|
+
############################################
|
536
|
+
require "openai"
|
537
|
+
require "json"
|
538
|
+
|
539
|
+
class KnowledgeGraphGenerator
|
540
|
+
def initialize(api_key)
|
541
|
+
@client = OpenAI::Client.new(access_token: api_key)
|
542
|
+
end
|
543
|
+
|
544
|
+
def generate_graph(text)
|
545
|
+
prompt = <<~PROMPT
|
546
|
+
Given the following paragraph, create a knowledge graph.
|
547
|
+
Output the result as a JSON object with the following structure:
|
548
|
+
{
|
549
|
+
"nodes": [
|
550
|
+
{"id": "unique_id", "label": "concept or entity", "type": "entity_type"}
|
551
|
+
],
|
552
|
+
"edges": [
|
553
|
+
{"source": "source_id", "target": "target_id", "label": "relationship"}
|
554
|
+
]
|
555
|
+
}
|
556
|
+
|
557
|
+
Paragraph:
|
558
|
+
#{text}
|
559
|
+
|
560
|
+
JSON Knowledge Graph:
|
561
|
+
PROMPT
|
562
|
+
|
563
|
+
response = @client.chat(
|
564
|
+
parameters: {
|
565
|
+
model: "gpt-4", # or "gpt-3.5-turbo" if you don't have GPT-4 access
|
566
|
+
messages: [{ role: "user", content: prompt }],
|
567
|
+
temperature: 0.7,
|
568
|
+
},
|
569
|
+
)
|
570
|
+
|
571
|
+
JSON.parse(response.dig("choices", 0, "message", "content"))
|
572
|
+
end
|
573
|
+
end
|
574
|
+
|
575
|
+
class KnowledgeGraph
|
576
|
+
attr_reader :nodes, :edges
|
577
|
+
|
578
|
+
def initialize(data)
|
579
|
+
@nodes = data["nodes"]
|
580
|
+
@edges = data["edges"]
|
581
|
+
end
|
582
|
+
|
583
|
+
def to_s
|
584
|
+
"Nodes:\n" + @nodes.map { |n| " #{n["id"]}: #{n["label"]} (#{n["type"]})" }.join("\n") +
|
585
|
+
"\nEdges:\n" + @edges.map { |e|
|
586
|
+
" #{e["source"]} -> #{e["target"]}: #{e["label"]}"
|
587
|
+
}.join("\n")
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
# Usage
|
592
|
+
generator = KnowledgeGraphGenerator.new("your-openai-api-key")
|
593
|
+
|
594
|
+
text = "Artificial Intelligence (AI) is a broad field of computer science focused on creating
|
595
|
+
intelligent machines that can perform tasks that typically require human intelligence. Machine
|
596
|
+
Learning, a subset of AI, uses statistical techniques to give computer systems the ability to
|
597
|
+
'learn' from data, without being explicitly programmed. Deep Learning, a further
|
598
|
+
specialization of Machine Learning, uses neural networks with many layers (hence 'deep') to
|
599
|
+
analyze various factors of data."
|
600
|
+
|
601
|
+
graph_data = generator.generate_graph(text)
|
602
|
+
graph = KnowledgeGraph.new(graph_data)
|
603
|
+
|
604
|
+
puts graph
|
605
|
+
|
606
|
+
|
607
|
+
############################################
|
608
|
+
require "json"
|
609
|
+
|
610
|
+
class KnowledgeGraph
|
611
|
+
attr_reader :nodes, :edges
|
612
|
+
|
613
|
+
def initialize(data)
|
614
|
+
@nodes = data["nodes"]
|
615
|
+
@edges = data["edges"]
|
616
|
+
end
|
617
|
+
|
618
|
+
def to_s
|
619
|
+
"Nodes:\n" + @nodes.map { |n| " #{n["id"]}: #{n["label"]} (#{n["type"]})" }.join("\n") +
|
620
|
+
"\nEdges:\n" + @edges.map { |e|
|
621
|
+
" #{e["source"]} -> #{e["target"]}: #{e["label"]}"
|
622
|
+
}.join("\n")
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
626
|
+
# Assuming the JSON is stored in a variable called 'json_data'
|
627
|
+
graph_data = JSON.parse(json_data)
|
628
|
+
graph = KnowledgeGraph.new(graph_data)
|
629
|
+
|
630
|
+
puts graph
|
631
|
+
|
632
|
+
pin "vis-network", to: "https://ga.jspm.io/npm:vis-network@9.1.6/standalone/esm/vis-network.js"
|
633
|
+
|
634
|
+
|
635
|
+
############################################
|
636
|
+
# app/controllers/knowledge_graphs_controller.rb
|
637
|
+
class KnowledgeGraphsController < ApplicationController
|
638
|
+
def show
|
639
|
+
@graph_data = {
|
640
|
+
nodes: [
|
641
|
+
{ id: 1, label: "Resident", group: "Person" },
|
642
|
+
{ id: 2, label: "Bossier City", group: "Location" },
|
643
|
+
{ id: 3, label: "Louisiana", group: "Location" },
|
644
|
+
{ id: 4, label: "2021 Tahoe LS", group: "Vehicle" },
|
645
|
+
{ id: 5, label: "Poor eyesight", group: "Condition" },
|
646
|
+
{ id: 6, label: "Driving restriction", group: "Regulation" },
|
647
|
+
],
|
648
|
+
edges: [
|
649
|
+
{ from: 1, to: 2, label: "resides in" },
|
650
|
+
{ from: 2, to: 3, label: "located in" },
|
651
|
+
{ from: 1, to: 4, label: "owns" },
|
652
|
+
{ from: 1, to: 5, label: "has condition" },
|
653
|
+
{ from: 1, to: 6, label: "subject to" },
|
654
|
+
{ from: 6, to: 4, label: "applies to" },
|
655
|
+
{ from: 5, to: 6, label: "causes" },
|
656
|
+
],
|
657
|
+
}
|
658
|
+
end
|
659
|
+
end
|
660
|
+
|
661
|
+
# config/routes.rb
|
662
|
+
Rails.application.routes.draw do
|
663
|
+
get "knowledge_graph", to: "knowledge_graphs#show"
|
664
|
+
# ... other routes ...
|
665
|
+
end
|
666
|
+
|
667
|
+
# app/controllers/knowledge_graphs_controller.rb
|
668
|
+
class KnowledgeGraphsController < ApplicationController
|
669
|
+
def new
|
670
|
+
@knowledge_graph = KnowledgeGraph.new
|
671
|
+
end
|
672
|
+
|
673
|
+
def create
|
674
|
+
@knowledge_graph = KnowledgeGraph.new(knowledge_graph_params)
|
675
|
+
if @knowledge_graph.save
|
676
|
+
redirect_to @knowledge_graph
|
677
|
+
else
|
678
|
+
render :new
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
def show
|
683
|
+
@knowledge_graph = KnowledgeGraph.find(params[:id])
|
684
|
+
@graph_data = JSON.parse(@knowledge_graph.graph_data)
|
685
|
+
end
|
686
|
+
|
687
|
+
private
|
688
|
+
|
689
|
+
def knowledge_graph_params
|
690
|
+
params.require(:knowledge_graph).permit(:input_text)
|
691
|
+
end
|
692
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Agent to Agent (a2a) Protocol
|
2
|
+
|
3
|
+
Google just pulically announted their A2A public protocol for inter-agent coordination and discovery. Its a pretty thick specification much heavier and more complete that what is being proposed here within the Agent99 reference implementation; however, it is at the highest levels consistent with a centralized well-known server, use of HTML for inter-agent communication payloads of JSON packages; and, of course, agents a hetro implementations from anywhere but having the one communication standard in common.
|
4
|
+
|
5
|
+
## Introductory Blog Post
|
6
|
+
|
7
|
+
https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
|
8
|
+
|
9
|
+
## Complete Specification
|
10
|
+
|
11
|
+
It contains sample applications in python and JavaShit
|
12
|
+
|
13
|
+
https://github.com/google/A2A
|
@@ -4,6 +4,8 @@
|
|
4
4
|
|
5
5
|
Agent99 provides a robust control system that allows for dynamic management of agents during runtime. Control actions enable administrative operations and state management without requiring agent restarts or redeployment.
|
6
6
|
|
7
|
+

|
8
|
+
|
7
9
|
### Built-in Control Actions
|
8
10
|
|
9
11
|
The framework includes several built-in control actions:
|