HeyChriss commited on
Commit
d0deb09
·
1 Parent(s): 937f5f4
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ .conda
__pycache__/chat_model.cpython-311.pyc ADDED
Binary file (4.61 kB). View file
 
__pycache__/system_prompt.cpython-311.pyc ADDED
Binary file (2.01 kB). View file
 
app.py CHANGED
@@ -1,43 +1,34 @@
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
 
 
 
 
 
3
 
4
 
5
  def respond(
6
  message,
7
- history: list[dict[str, str]],
8
  system_message,
9
  max_tokens,
10
  temperature,
11
  top_p,
12
- hf_token: gr.OAuthToken,
13
  ):
14
- """
15
- For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
16
- """
17
- client = InferenceClient(token=hf_token.token, model="openai/gpt-oss-20b")
18
-
19
- messages = [{"role": "system", "content": system_message}]
20
-
21
- messages.extend(history)
22
-
23
- messages.append({"role": "user", "content": message})
24
-
25
- response = ""
26
-
27
- for message in client.chat_completion(
28
- messages,
29
  max_tokens=max_tokens,
30
- stream=True,
31
  temperature=temperature,
32
  top_p=top_p,
33
  ):
34
- choices = message.choices
35
- token = ""
36
- if len(choices) and choices[0].delta.content:
37
- token = choices[0].delta.content
38
-
39
- response += token
40
- yield response
41
 
42
 
43
  """
@@ -46,22 +37,22 @@ For information on how to customize the ChatInterface, peruse the gradio docs: h
46
  chatbot = gr.ChatInterface(
47
  respond,
48
  additional_inputs=[
49
- gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
50
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
51
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
52
- gr.Slider(
53
- minimum=0.1,
54
- maximum=1.0,
55
- value=0.95,
56
- step=0.05,
57
- label="Top-p (nucleus sampling)",
58
  ),
59
  ],
60
  )
61
 
62
  with gr.Blocks() as demo:
63
- with gr.Sidebar():
64
- gr.LoginButton()
 
 
 
 
 
 
65
  chatbot.render()
66
 
67
 
 
1
  import gradio as gr
2
+
3
+ from chat_model import IlographChatModel
4
+
5
+
6
+ # Load the model once at startup so every request reuses it.
7
+ chat_model = IlographChatModel()
8
 
9
 
10
  def respond(
11
  message,
12
+ history,
13
  system_message,
14
  max_tokens,
15
  temperature,
16
  top_p,
 
17
  ):
18
+ messages = chat_model.build_messages(
19
+ system_prompt=system_message,
20
+ history=history,
21
+ user_message=message,
22
+ )
23
+
24
+ # Delegate token streaming to the model wrapper
25
+ for partial in chat_model.generate_stream(
26
+ messages=messages,
 
 
 
 
 
 
27
  max_tokens=max_tokens,
 
28
  temperature=temperature,
29
  top_p=top_p,
30
  ):
31
+ yield partial
 
 
 
 
 
 
32
 
33
 
34
  """
 
37
  chatbot = gr.ChatInterface(
38
  respond,
39
  additional_inputs=[
40
+ gr.Textbox(
41
+ value=chat_model.default_system_prompt,
42
+ label="System message",
 
 
 
 
 
 
43
  ),
44
  ],
45
  )
46
 
47
  with gr.Blocks() as demo:
48
+ gr.Markdown(
49
+ "Note: **this is a lightweight 3B Ilograph model intended for basic diagrams.** "
50
+ "For more complex modeling tasks, use the newer, larger Ilograph models. The current model is **Brigham-Young-University/Qwen2.5-Coder-3B-Ilograph-Instruct**."
51
+ " If you want to use the larger model, you can check the [Hugging Face model page](https://huggingface.co/models?other=ilograph)."
52
+ )
53
+ gr.Markdown(
54
+ "The model might take a few seconds to load, I don't have GPU so it's slow."
55
+ )
56
  chatbot.render()
57
 
58
 
chat_model.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, Generator, List, Optional
2
+
3
+ import torch
4
+ from transformers import AutoModelForCausalLM, AutoTokenizer
5
+
6
+ from system_prompt import build_default_system_prompt
7
+
8
+
9
+ class IlographChatModel(object):
10
+ """
11
+ Thin OOP wrapper around the Qwen3 Ilograph model.
12
+
13
+ Responsibility:
14
+ - Load tokenizer/model once at startup
15
+ - Expose a simple streaming text interface for chat-style messages
16
+ """
17
+
18
+ def __init__(
19
+ self,
20
+ model_id="Brigham-Young-University/Qwen2.5-Coder-3B-Ilograph-Instruct",
21
+ device_map=None,
22
+ dtype=None,
23
+ ):
24
+ self.model_id = model_id
25
+
26
+ # Choose sensible defaults based on available hardware.
27
+ if device_map is None or dtype is None:
28
+ if torch.cuda.is_available():
29
+ # On GPU (e.g. HF Space with GPU), let transformers/accelerate
30
+ # decide how to place weights and use bfloat16 for speed.
31
+ if device_map is None:
32
+ device_map = "auto"
33
+ if dtype is None:
34
+ dtype = torch.bfloat16
35
+ else:
36
+ # On CPU-only (local machine or CPU Space), force everything
37
+ # onto CPU with full precision for correctness.
38
+ if device_map is None:
39
+ device_map = {"": "cpu"}
40
+ if dtype is None:
41
+ dtype = torch.float32
42
+
43
+ self.device_map = device_map
44
+ self.dtype = dtype
45
+
46
+ self.tokenizer = AutoTokenizer.from_pretrained(
47
+ model_id,
48
+ trust_remote_code=True,
49
+ )
50
+ self.model = AutoModelForCausalLM.from_pretrained(
51
+ model_id,
52
+ trust_remote_code=True,
53
+ torch_dtype=self.dtype,
54
+ device_map=self.device_map,
55
+ )
56
+
57
+ if self.tokenizer.pad_token_id is None:
58
+ # Many causal LMs do not define a pad token, but generate() expects one
59
+ self.tokenizer.pad_token = self.tokenizer.eos_token
60
+
61
+ # Cache the default system prompt so we only load the schema once
62
+ self._default_system_prompt = build_default_system_prompt()
63
+
64
+ @property
65
+ def default_system_prompt(self):
66
+ return self._default_system_prompt
67
+
68
+ def build_messages(
69
+ self,
70
+ system_prompt,
71
+ history,
72
+ user_message,
73
+ ):
74
+ messages = []
75
+
76
+ system = system_prompt.strip() if system_prompt else self.default_system_prompt
77
+ messages.append({"role": "system", "content": system})
78
+
79
+ # Gradio already provides history as {role, content} dicts
80
+ if history:
81
+ messages.extend(history)
82
+
83
+ messages.append({"role": "user", "content": user_message})
84
+
85
+ return messages
86
+
87
+ def generate_stream(
88
+ self,
89
+ messages,
90
+ max_tokens,
91
+ temperature,
92
+ top_p,
93
+ ):
94
+ """
95
+ Synchronous "streaming" generator for Gradio.
96
+
97
+ For simplicity we generate the full response once and then
98
+ yield it in small chunks so the UI can update incrementally.
99
+ """
100
+ # Qwen's apply_chat_template can return either a tensor or a BatchEncoding.
101
+ encoded = self.tokenizer.apply_chat_template(
102
+ messages,
103
+ add_generation_prompt=True,
104
+ return_tensors="pt",
105
+ )
106
+
107
+ # Normalise to a plain tensor so generate() receives the right type.
108
+ if hasattr(encoded, "input_ids"):
109
+ input_ids = encoded["input_ids"]
110
+ else:
111
+ input_ids = encoded
112
+
113
+ input_ids = input_ids.to(self.model.device)
114
+
115
+ with torch.no_grad():
116
+ output_ids = self.model.generate(
117
+ input_ids=input_ids,
118
+ max_new_tokens=256,
119
+ temperature=0.5,
120
+ do_sample=True,
121
+ eos_token_id=self.tokenizer.eos_token_id,
122
+ pad_token_id=self.tokenizer.pad_token_id,
123
+ )
124
+
125
+ # Only keep newly generated tokens
126
+ generated_ids = output_ids[0, input_ids.shape[-1] :]
127
+ full_text = self.tokenizer.decode(
128
+ generated_ids,
129
+ skip_special_tokens=True,
130
+ )
131
+
132
+ # Wrap in a Markdown code block so the chat UI preserves
133
+ # spaces and indentation (critical for YAML / IDL output).
134
+ formatted = "```yaml\n" + full_text.strip("\n") + "\n```"
135
+ yield formatted
136
+
idl-2025-11-03.schema.json ADDED
@@ -0,0 +1,567 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://ilograph.com/schemas/idl-2025-11-03.json",
4
+ "title": "Ilograph Diagram Language (IDL) - November 2025 Version",
5
+ "description": "Schema for Ilograph YAML diagram specifications based on 2025-11-03 spec",
6
+ "type": "object",
7
+ "properties": {
8
+ "resources": {
9
+ "$ref": "#/$defs/resourceArray"
10
+ },
11
+ "perspectives": {
12
+ "$ref": "#/$defs/perspectiveArray"
13
+ },
14
+ "imports": {
15
+ "$ref": "#/$defs/importArray"
16
+ },
17
+ "contexts": {
18
+ "$ref": "#/$defs/contextArray"
19
+ },
20
+ "description": {
21
+ "type": "string",
22
+ "description": "A description of the diagram that appears at the top of the overview page. Has support for markdown, and can contain multiple lines."
23
+ },
24
+ "defaultContextDisplayName": {
25
+ "type": "string",
26
+ "description": "The display name of the default context"
27
+ }
28
+ },
29
+ "$defs": {
30
+ "resourceArray": {
31
+ "type": "array",
32
+ "description": "An array of resources (the resource tree)",
33
+ "items": {
34
+ "$ref": "#/$defs/resource"
35
+ }
36
+ },
37
+
38
+ "perspectiveArray": {
39
+ "type": "array",
40
+ "description": "An array of perspectives",
41
+ "items": {
42
+ "$ref": "#/$defs/perspective"
43
+ }
44
+ },
45
+
46
+ "importArray": {
47
+ "type": "array",
48
+ "description": "An array of imports",
49
+ "items": {
50
+ "$ref": "#/$defs/import"
51
+ }
52
+ },
53
+
54
+ "contextArray": {
55
+ "type": "array",
56
+ "description": "An array of contexts",
57
+ "items": {
58
+ "$ref": "#/$defs/context"
59
+ }
60
+ },
61
+
62
+ "resource": {
63
+ "type": "object",
64
+ "description": "Resources are the building blocks of Ilograph diagrams. Resources can appear in multiple perspectives.",
65
+ "required": ["name"],
66
+ "properties": {
67
+ "name": {
68
+ "type": "string",
69
+ "description": "The name of the resource. Used as the identifier if id is not provided."
70
+ },
71
+ "id": {
72
+ "type": "string",
73
+ "pattern": "^[^/\\^*\\[\\],^]*$",
74
+ "description": "A substitute identifier for the resource. Cannot contain restricted characters."
75
+ },
76
+ "subtitle": {
77
+ "type": "string",
78
+ "description": "The subtitle of the resource (appears below the resource name)"
79
+ },
80
+ "description": {
81
+ "oneOf": [
82
+ { "type": "string" },
83
+ { "$ref": "#/$defs/descriptionObject" }
84
+ ],
85
+ "description": "The description of the resource. Supports markdown and can contain multiple lines or be defined as key-value pairs."
86
+ },
87
+ "color": {
88
+ "type": "string",
89
+ "pattern": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$|^[a-zA-Z]+$",
90
+ "default": "dimgray",
91
+ "description": "Text color. Any X11 color name or hex value like #FF00FF."
92
+ },
93
+ "backgroundColor": {
94
+ "type": "string",
95
+ "pattern": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$|^[a-zA-Z]+$",
96
+ "default": "white",
97
+ "description": "Background color. Any X11 color name or hex value like #FF00FF."
98
+ },
99
+ "style": {
100
+ "type": "string",
101
+ "enum": ["default", "plural", "dashed", "outline", "flat"],
102
+ "default": "default",
103
+ "description": "Resource border style. When set to plural, rendered as multiple boxes."
104
+ },
105
+ "abstract": {
106
+ "type": "boolean",
107
+ "default": false,
108
+ "description": "When set to true, other resources may inherit from this resource using instanceOf."
109
+ },
110
+ "instanceOf": {
111
+ "type": "string",
112
+ "description": "When specified, this resource inherits all properties (other than id/name) and child resources of the specified abstract resource."
113
+ },
114
+ "children": {
115
+ "$ref": "#/$defs/resourceArray",
116
+ "description": "An array of child resources"
117
+ },
118
+ "icon": {
119
+ "type": "string",
120
+ "description": "An icon path for the resource"
121
+ },
122
+ "iconStyle": {
123
+ "type": "string",
124
+ "enum": ["default", "silhouette"],
125
+ "default": "default",
126
+ "description": "Controls how the icon is rendered."
127
+ },
128
+ "url": {
129
+ "type": "string",
130
+ "format": "uri",
131
+ "description": "URL for the resource. If defined, a link icon appears when selected."
132
+ },
133
+ "layout": {
134
+ "$ref": "#/$defs/layout"
135
+ }
136
+ },
137
+ "additionalProperties": false
138
+ },
139
+
140
+ "descriptionObject": {
141
+ "type": "object",
142
+ "description": "Key-value pair description format"
143
+ },
144
+
145
+ "perspective": {
146
+ "type": "object",
147
+ "description": "Each perspective gives a unique view of the relations between resources.",
148
+ "required": ["name"],
149
+ "properties": {
150
+ "id": {
151
+ "type": "string",
152
+ "description": "A substitute identifier for the perspective."
153
+ },
154
+ "name": {
155
+ "type": "string",
156
+ "description": "Name of the perspective. Used as unique identifier if id not provided."
157
+ },
158
+ "color": {
159
+ "type": "string",
160
+ "pattern": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$|^[a-zA-Z]+$",
161
+ "default": "royalblue",
162
+ "description": "Color of the perspective. Any X11 color name or hex value."
163
+ },
164
+ "relations": {
165
+ "$ref": "#/$defs/relationArray",
166
+ "description": "An array of relations"
167
+ },
168
+ "sequence": {
169
+ "$ref": "#/$defs/sequence",
170
+ "description": "Sequence object for sequence perspectives"
171
+ },
172
+ "notes": {
173
+ "type": "string",
174
+ "description": "Notes that appear in the notes panel and overview page. Supports markdown."
175
+ },
176
+ "extends": {
177
+ "type": "string",
178
+ "description": "Previously-defined perspective(s) that this perspective extends."
179
+ },
180
+ "walkthrough": {
181
+ "$ref": "#/$defs/slideArray",
182
+ "description": "An array of slides forming the walkthrough"
183
+ },
184
+ "aliases": {
185
+ "$ref": "#/$defs/aliasArray",
186
+ "description": "An array of aliases"
187
+ },
188
+ "overrides": {
189
+ "$ref": "#/$defs/overrideArray",
190
+ "description": "An array of overrides"
191
+ },
192
+ "orientation": {
193
+ "type": "string",
194
+ "enum": ["leftToRight", "topToBottom", "ring"],
195
+ "default": "leftToRight",
196
+ "description": "Which direction the perspective is oriented. Does not affect sequence perspectives."
197
+ },
198
+ "options": {
199
+ "$ref": "#/$defs/perspectiveOptions",
200
+ "description": "Additional options for this perspective"
201
+ }
202
+ },
203
+ "additionalProperties": false,
204
+ "oneOf": [
205
+ {
206
+ "required": ["relations"],
207
+ "description": "Perspectives with relations are relation perspectives"
208
+ },
209
+ {
210
+ "required": ["sequence"],
211
+ "description": "Perspectives with sequence are sequence perspectives"
212
+ }
213
+ ]
214
+ },
215
+
216
+ "relationArray": {
217
+ "type": "array",
218
+ "description": "Relations define how resources are related to each other in the perspective.",
219
+ "items": {
220
+ "$ref": "#/$defs/relation"
221
+ }
222
+ },
223
+
224
+ "relation": {
225
+ "type": "object",
226
+ "description": "Relations define how resources are related to each other in the perspective. Each relation must define from or to.",
227
+ "properties": {
228
+ "from": {
229
+ "type": "string",
230
+ "description": "Reference(s) to the dependent (left-side) resource(s)"
231
+ },
232
+ "to": {
233
+ "type": "string",
234
+ "description": "Reference(s) to the independent (right-side) resource(s)"
235
+ },
236
+ "via": {
237
+ "type": "string",
238
+ "description": "Reference(s) to resource(s) this relation passes through"
239
+ },
240
+ "label": {
241
+ "type": "string",
242
+ "description": "Label that appears above the arrow(s)"
243
+ },
244
+ "description": {
245
+ "type": "string",
246
+ "description": "Extended description for hover text. Supports markdown."
247
+ },
248
+ "arrowDirection": {
249
+ "type": "string",
250
+ "enum": ["forward", "backward", "bidirectional"],
251
+ "default": "forward",
252
+ "description": "Arrow direction relative to perspective orientation."
253
+ },
254
+ "color": {
255
+ "type": "string",
256
+ "pattern": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$|^[a-zA-Z]+$",
257
+ "default": "#303030",
258
+ "description": "Arrow and text color. Any X11 color name or hex value."
259
+ },
260
+ "secondary": {
261
+ "type": "boolean",
262
+ "default": false,
263
+ "description": "If true, relation will not affect perspective layout. Does not affect ring perspectives."
264
+ }
265
+ },
266
+ "oneOf": [{ "required": ["from"] }, { "required": ["to"] }],
267
+ "additionalProperties": false
268
+ },
269
+
270
+ "sequence": {
271
+ "type": "object",
272
+ "description": "Sequence defines how resources are related in a sequence of steps.",
273
+ "required": ["start"],
274
+ "properties": {
275
+ "start": {
276
+ "type": "string",
277
+ "description": "Starting resource in the sequence, or none to have first step come from off-screen"
278
+ },
279
+ "steps": {
280
+ "$ref": "#/$defs/stepArray",
281
+ "description": "An array of steps in the sequence"
282
+ }
283
+ },
284
+ "additionalProperties": false
285
+ },
286
+
287
+ "stepArray": {
288
+ "type": "array",
289
+ "description": "Steps in a sequence define the steps between resources and their labels.",
290
+ "items": {
291
+ "$ref": "#/$defs/step"
292
+ }
293
+ },
294
+
295
+ "step": {
296
+ "type": "object",
297
+ "description": "Steps in a sequence define the steps between resources and their labels. Each step must define to, toAndBack, toAsync, restartAt, or subSequence.",
298
+ "properties": {
299
+ "to": {
300
+ "type": "string",
301
+ "description": "Resource this step goes to"
302
+ },
303
+ "toAndBack": {
304
+ "type": "string",
305
+ "description": "Resource this step goes to with automatic return"
306
+ },
307
+ "toAsync": {
308
+ "type": "string",
309
+ "description": "Resource this step goes to asynchronously (drawn with dashed arrows)"
310
+ },
311
+ "restartAt": {
312
+ "type": "string",
313
+ "description": "Resource to pass control to without drawing an arrow"
314
+ },
315
+ "subSequence": {
316
+ "$ref": "#/$defs/subSequence",
317
+ "description": "A sub-sequence object"
318
+ },
319
+ "label": {
320
+ "type": "string",
321
+ "description": "Label that appears above the arrow"
322
+ },
323
+ "description": {
324
+ "type": "string",
325
+ "description": "Extended description for hover text. Supports markdown."
326
+ },
327
+ "bidirectional": {
328
+ "type": "boolean",
329
+ "default": false,
330
+ "description": "If true, arrows are shown with arrowheads on both ends."
331
+ },
332
+ "color": {
333
+ "type": "string",
334
+ "pattern": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$|^[a-zA-Z]+$",
335
+ "default": "#303030",
336
+ "description": "Arrow and text color. Any X11 color name or hex value."
337
+ }
338
+ },
339
+ "oneOf": [
340
+ { "required": ["to"] },
341
+ { "required": ["toAndBack"] },
342
+ { "required": ["toAsync"] },
343
+ { "required": ["restartAt"] },
344
+ { "required": ["subSequence"] }
345
+ ],
346
+ "additionalProperties": false
347
+ },
348
+
349
+ "subSequence": {
350
+ "type": "object",
351
+ "description": "Sub-sequences appear as colored boxes in sequences that can be zoomed into.",
352
+ "required": ["name"],
353
+ "properties": {
354
+ "name": {
355
+ "type": "string",
356
+ "pattern": "^[^/~]*$",
357
+ "description": "Name of the sub-sequence. Cannot contain / or ~"
358
+ },
359
+ "color": {
360
+ "type": "string",
361
+ "pattern": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$|^[a-zA-Z]+$",
362
+ "description": "Box and text color. Any X11 color name or hex value. Defaults to perspective color."
363
+ },
364
+ "notes": {
365
+ "type": "string",
366
+ "description": "Notes that appear when zoomed into the sub-sequence. Supports markdown."
367
+ },
368
+ "steps": {
369
+ "$ref": "#/$defs/stepArray",
370
+ "description": "An array of steps"
371
+ }
372
+ },
373
+ "additionalProperties": false
374
+ },
375
+
376
+ "aliasArray": {
377
+ "type": "array",
378
+ "description": "Aliases give convenient names to resource references.",
379
+ "items": {
380
+ "$ref": "#/$defs/alias"
381
+ }
382
+ },
383
+
384
+ "alias": {
385
+ "type": "object",
386
+ "description": "Convenient names for resource references.",
387
+ "required": ["alias", "for"],
388
+ "properties": {
389
+ "alias": {
390
+ "type": "string",
391
+ "pattern": "^[^/\\^*\\[\\],^]*$",
392
+ "description": "Identifier for this alias. Can override existing resource id."
393
+ },
394
+ "for": {
395
+ "type": "string",
396
+ "description": "Value of this alias, typically comma-separated resource identifiers"
397
+ }
398
+ },
399
+ "additionalProperties": false
400
+ },
401
+
402
+ "overrideArray": {
403
+ "type": "array",
404
+ "description": "Overrides are used to override parent and sizes of resources in a perspective.",
405
+ "items": {
406
+ "$ref": "#/$defs/override"
407
+ }
408
+ },
409
+
410
+ "override": {
411
+ "type": "object",
412
+ "description": "Override resource properties in a perspective.",
413
+ "required": ["resourceId"],
414
+ "properties": {
415
+ "resourceId": {
416
+ "type": "string",
417
+ "description": "Resource(s) to override in the perspective"
418
+ },
419
+ "parentId": {
420
+ "type": "string",
421
+ "description": "Different parent to assign, or none for no parent"
422
+ },
423
+ "scale": {
424
+ "type": "number",
425
+ "description": "Size adjustment for specified resource(s)"
426
+ }
427
+ },
428
+ "additionalProperties": false
429
+ },
430
+
431
+ "slideArray": {
432
+ "type": "array",
433
+ "description": "Slides form the walkthrough for a perspective.",
434
+ "items": {
435
+ "$ref": "#/$defs/slide"
436
+ }
437
+ },
438
+
439
+ "slide": {
440
+ "type": "object",
441
+ "description": "A slide in a perspective walkthrough.",
442
+ "properties": {
443
+ "text": {
444
+ "type": "string",
445
+ "description": "Text accompanying the slide. If not present, previous slide's text is used."
446
+ },
447
+ "select": {
448
+ "type": "string",
449
+ "description": "Resource(s) to select. Selected resources displayed prominently, others hidden."
450
+ },
451
+ "expand": {
452
+ "type": "string",
453
+ "description": "Resource or sub-sequence to expand (make full-screen). Use ^ for none."
454
+ },
455
+ "highlight": {
456
+ "type": "string",
457
+ "description": "Resource(s) to highlight with animated border."
458
+ },
459
+ "detail": {
460
+ "type": "number",
461
+ "minimum": 0.001,
462
+ "maximum": 1,
463
+ "default": 1,
464
+ "description": "Level of detail used during the slide. Range: 0.001 (very low) to 1 (full detail)."
465
+ }
466
+ },
467
+ "additionalProperties": false
468
+ },
469
+
470
+ "context": {
471
+ "type": "object",
472
+ "description": "Each context defines a view of the diagram resources.",
473
+ "required": ["name"],
474
+ "properties": {
475
+ "name": {
476
+ "type": "string",
477
+ "description": "Context name. Must be unique and cannot be Default."
478
+ },
479
+ "roots": {
480
+ "$ref": "#/$defs/contextEntryArray",
481
+ "description": "Context entries forming a tree structure"
482
+ },
483
+ "extends": {
484
+ "type": "string",
485
+ "description": "Previously-defined context(s) that this context extends."
486
+ },
487
+ "hidden": {
488
+ "type": "boolean",
489
+ "default": false,
490
+ "description": "If true, context not shown in dropdown."
491
+ }
492
+ },
493
+ "additionalProperties": false
494
+ },
495
+
496
+ "contextEntryArray": {
497
+ "type": "array",
498
+ "description": "Context entries form a tree-like structure for defining context.",
499
+ "items": {
500
+ "$ref": "#/$defs/contextEntry"
501
+ }
502
+ },
503
+
504
+ "contextEntry": {
505
+ "type": "object",
506
+ "description": "Context entry defining resource visibility.",
507
+ "required": ["resourceId"],
508
+ "properties": {
509
+ "resourceId": {
510
+ "type": "string",
511
+ "description": "Resource identifier(s) for this entry."
512
+ },
513
+ "children": {
514
+ "$ref": "#/$defs/contextEntryArray",
515
+ "description": "Child context entries. Cannot be defined if multiple resources specified in resourceId."
516
+ }
517
+ },
518
+ "additionalProperties": false
519
+ },
520
+
521
+ "layout": {
522
+ "type": "object",
523
+ "description": "Layout parameters govern how child elements are laid out inside a parent.",
524
+ "properties": {
525
+ "compactness": {
526
+ "type": "number",
527
+ "minimum": 0.1,
528
+ "maximum": 1,
529
+ "default": 1,
530
+ "description": "How compactly child resources are rendered. Affects only context resources with more than one child."
531
+ },
532
+ "sizes": {
533
+ "type": "string",
534
+ "enum": ["proportional", "uniform", "auto"],
535
+ "default": "auto",
536
+ "description": "How child resource sizes are determined."
537
+ }
538
+ },
539
+ "additionalProperties": false
540
+ },
541
+
542
+ "perspectiveOptions": {
543
+ "type": "object",
544
+ "description": "Additional options for the perspective.",
545
+ "properties": {},
546
+ "additionalProperties": true
547
+ },
548
+
549
+ "import": {
550
+ "type": "object",
551
+ "description": "Imports define a list of diagrams to import and their namespaces.",
552
+ "required": ["from", "namespace"],
553
+ "properties": {
554
+ "from": {
555
+ "type": "string",
556
+ "description": "The diagram to import"
557
+ },
558
+ "namespace": {
559
+ "type": "string",
560
+ "pattern": "^[^/\\^*\\[\\],^]*$",
561
+ "description": "Namespace prefix for imported resources and perspectives. Cannot contain restricted characters."
562
+ }
563
+ },
564
+ "additionalProperties": false
565
+ }
566
+ }
567
+ }
requirements.txt ADDED
Binary file (2.34 kB). View file
 
system_prompt.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+
4
+
5
+ def load_json(filepath):
6
+ with open(filepath, "r") as f:
7
+ return json.load(f)
8
+
9
+
10
+ def build_default_system_prompt(schema_path="idl-2025-11-03.schema.json"):
11
+ """
12
+ Build the IDL-focused system prompt based on the JSON schema file.
13
+ """
14
+ # Allow running from other working directories by resolving relative to this file
15
+ base_dir = os.path.dirname(os.path.abspath(__file__))
16
+ full_path = os.path.join(base_dir, schema_path)
17
+
18
+ schema = load_json(full_path)
19
+
20
+ system_prompt = f"""
21
+ You are an expert in the Ilograph Diagram Language (IDL). You have been trained on data that is formatted in the following way:
22
+
23
+ {json.dumps(schema, indent=2)}
24
+
25
+ Your task is to create a valid IDL specification for the diagram. You will be given an instruction of what to create, and you will need to create a valid IDL specification for the diagram.
26
+
27
+ CRITICAL RULES:
28
+ - NEVER use JSON format
29
+ - NEVER use Mermaid syntax
30
+ - NEVER use any format except ilograph YAML
31
+ - ALWAYS include resources: and perspectives:
32
+ - Use YAML syntax with proper indentation
33
+
34
+ Here is the instruction:
35
+ """.strip()
36
+
37
+ return system_prompt
38
+
39
+