Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions examples/bookstore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# N::Chapter {
# chapter_index: I64
# }
#
# N::SubChapter {
# title: String,
# content: String
# }
#
# E::Contains {
# From: Chapter,
# To: SubChapter,
# Properties: {
# }
# }
#
# V::Embedding {
# chunk: String
# }
#
# E::EmbeddingOf {
# From: SubChapter,
# To: Embedding,
# Properties: {
# chunk: String
# }
# }

# QUERY loaddocs_rag(chapters: [{ id: I64, subchapters: [{ title: String, content: String, chunks: [{chunk: String, vector: [F64]}]}] }]) =>
# FOR {id, subchapters} IN chapters {
# chapter_node <- AddN<Chapter>({ chapter_index: id })
# FOR {title, content, chunks} IN subchapters {
# subchapter_node <- AddN<SubChapter>({ title: title, content: content })
# AddE<Contains>::From(chapter_node)::To(subchapter_node)
# FOR {chunk, vector} IN chunks {
# vec <- AddV<Embedding>(vector)
# AddE<EmbeddingOf>({chunk: chunk})::From(subchapter_node)::To(vec)
# }
# }
# }
# RETURN "Success"

# QUERY searchdocs_rag(query: [F64], k: I32) =>
# vecs <- SearchV<Embedding>(query, k)
# subchapters <- vecs::In<EmbeddingOf>
# RETURN subchapters::{title, content}

# QUERY edge_node() =>
# e <- N<Chapter>::OutE<Contains>
# RETURN e

# QUERY edge_node_id(id: ID) =>
# e <- N<Chapter>::OutE<Contains>(id)
# RETURN e
#

import helix

db = helix.Db()

class Chapter(db.Node):
index: helix.I64

db.index(Chapter.index, unique=True)

class SubChapter(db.Node):
title: helix.String
content: helix.String

embedding: SubChapterEmbedding
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: SubChapterEmbedding used before definition (defined on line 72)

Suggested change
embedding: SubChapterEmbedding
class SubChapterEmbedding(db.Vector(dimensions=1536, hnsw=helix.cosine)):
pass
class SubChapter(db.Node):
title: helix.String
content: helix.String
embedding: SubChapterEmbedding
Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/bookstore.py
Line: 70:70

Comment:
**syntax:** `SubChapterEmbedding` used before definition (defined on line 72)

```suggestion
class SubChapterEmbedding(db.Vector(dimensions=1536, hnsw=helix.cosine)):
    pass

class SubChapter(db.Node):
    title: helix.String
    content: helix.String

    embedding: SubChapterEmbedding
```

How can I resolve this? If you propose a fix, please make it concise.


class SubChapterEmbedding(db.Vector(dimensions=1536, hnsw=helix.cosine)):
pass

class Contains(db.Edge[Chapter, SubChapter]):
pass

class ArgChapter(helix.Struct):
id: helix.I64
subchapters: helix.List[ArgSubchapter]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: ArgSubchapter is defined on line 82 but referenced here as ArgSubChapter (capital C)

Suggested change
subchapters: helix.List[ArgSubchapter]
subchapters: helix.List[ArgSubchapter]
Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/bookstore.py
Line: 80:80

Comment:
**syntax:** `ArgSubchapter` is defined on line 82 but referenced here as `ArgSubChapter` (capital C)

```suggestion
    subchapters: helix.List[ArgSubchapter]
```

How can I resolve this? If you propose a fix, please make it concise.


class ArgSubchapter(helix.Struct):
title: helix.String
content: helix.String
chunk: helix.Vector

@db.query
def loaddocs_rag(chapters: helix.List[ArgChapter]) -> helix.String:
for c in chapters:
c_node = db.add_node(Chapter(index=c.id))

for sc in c.subchapters:
sc_node = db.add_node(SubChapter(
title=sc.title,
content=sc.content,
embedding=SubChapterEmbedding(sc.chunk)
))

db.add_edge(Contains(from=c_node, to=sc_node))

return "Success"

@db.query
def searchdocs_rag(query: helix.Vector, k: helix.I32) -> helix.Iterator[helix.Map[helix.String, helix.Value]]:
# TODO
vecs = db.search_vector(query, k)
chapters = vecs.incoming_nodes[Contains]
return chapters.map(lambda c: {"index": c.index})
Comment on lines +104 to +108
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: logic doesn't match the commented HelixQL query above (lines 43-46) - should get subchapters from vectors via EmbeddingOf edge, not chapters via Contains

Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/bookstore.py
Line: 104:108

Comment:
**logic:** logic doesn't match the commented HelixQL query above (lines 43-46) - should get `subchapters` from vectors via `EmbeddingOf` edge, not `chapters` via `Contains`

How can I resolve this? If you propose a fix, please make it concise.


@db.query
def edge_node() -> helix.Iterator[Contains]:
return db.nodes[Chapter].outgoing_edges[Contains]

@db.query
def edge_node_id(id: helix.Id[Chapter]) -> helix.Iterator[Contains]:
return db.nodes[Chapter](id=id).outgoing_edges[Contains]
72 changes: 72 additions & 0 deletions examples/bookstore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import hx from "helix";

const schema = hx.schema();

const Chapter = schema.defineNode("Chapter", {
index: I64,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: I64 is undefined - should be hx.I64

Suggested change
index: I64,
index: hx.I64,
Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/bookstore.ts
Line: 6:6

Comment:
**syntax:** `I64` is undefined - should be `hx.I64`

```suggestion
  index: hx.I64,
```

How can I resolve this? If you propose a fix, please make it concise.

});

schema.index(Chapter.index, { unique: true });

const SubChapter = schema.defineNode("SubChapter", {
title: hx.String,
content: hx.String,

embedding: SubChapterEmbedding,
});

const SubChapterEmbedding = schema.defineVector("SubChapterEmbedding", {
dimensions: 1536,
hnsw: hx.cosine,
});

const Contains = schema.defineEdge("Contains", {
from: Chapter,
to: SubChapter,
});

const ArgChapter = hx.Struct({
id: hx.I64,
subchapters: hx.List(ArgSubchapter),
});

const ArgSubChapter = hx.Struct({
title: hx.String,
content: hx.String,
chunk: hx.Vector,
});

const loadDocsRag = schema.query("loaddocs_rag", {
arguments: [hx.List(ArgChapter)],
returns: hx.String,
}, (db, [chapters]) => {
chapters.forEach((c) => {
const cNode = db.addNode(Chapter({ index: c.id }));

c.subchapters.forEach((sc) => {
const scNode = db.addNode(SubChapter({
title: sc.title,
content: sc.content,
embedding: SubChapterEmbedding(sc.chunk),
}));

db.addEdge(Contains({ from: cNode, to: scNode }));
});
});

return "Success";
});

const edgeNode = schema.query("edge_node", {
arguments: [],
returns: hx.Iterator(Contains),
}, (db, []) => {
return db.nodes[Chapter].outgoingEdges[Contains];
});

const edgeNodeId = schema.query("edge_node_id", {
arguments: [hx.Id(Chapter)],
returns: hx.Iterator(Contains),
}, (db, [id]) => {
return db.nodes[Chapter]({ id }).outgoingEdges[Contains];
});
5 changes: 5 additions & 0 deletions helix-ts/deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"tasks": {
"dev": "deno run --watch main.ts"
}
}
85 changes: 85 additions & 0 deletions helix-ts/ir.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
export const ExprKindString = { kind: "String" as const };
export const ExprKindI64 = { kind: "I64" as const };
export const ExprKindF64 = { kind: "F64" as const };
export const ExprKindBoolean = { kind: "Boolean" as const };
export const ExprKindVector = { kind: "Vector" as const };
export const ExprKindList = (item: ExprKind) => ({
kind: "List" as const,
item,
});
export const ExprKindStruct = (fields: Record<string, ExprKind>) => ({
kind: "Struct" as const,
fields,
});

export type ExprKind =
& MaybeNamed
& (
| typeof ExprKindString
| typeof ExprKindI64
| typeof ExprKindF64
| typeof ExprKindBoolean
| typeof ExprKindVector
| { kind: "List"; item: ExprKind }
| { kind: "Struct"; fields: Record<string, ExprKind> }
);

export type Expr = {
kind: ExprKind;
expr:
| { expr: "Argument"; index: number }
| { expr: "PropAccess"; target: Expr; field: string }
| { expr: "Literal"; value: any }
| { expr: "BinaryOp"; op: string; left: Expr; right: Expr }
| { expr: "Call"; func: string; args: Expr[] };
};

export type Statement =
| { stmt: "Expr"; expr: Expr }
| { stmt: "Return"; value: Expr };

export type Block = Statement[];

export type Named = { name: string };
export type MaybeNamed = Partial<Named>;

export type QueryName = string;
export type Query = Named & {
arguments: ExprKind[];
returns: ExprKind;
body: Block;
};

export type NodeName = string;
export type Node = Named & {
id: typeof ExprKindI64;
[_: string]: ExprKind;
};

export type EdgeName = string;
export type Edge = Named & {
id: typeof ExprKindI64;
from: NodeName;
to: NodeName;
};

export const GlobalVectorspaceName = `vectorspace_global` as const;
export type GlobalVectorspaceName = typeof GlobalVectorspaceName;
export type GlobalVectorspace = symbol;

export type VectorspaceName = string;
export type Vectorspace = Named & {
dimensions: number;
hnsw: any; // TODO
};

export type Schema = {
nodes: Record<NodeName, Node>;
indices: [{ on: NodeName; field: string; unique: boolean }];

edges: Record<EdgeName, Edge>;

vectorspaces: Record<GlobalVectorspaceName | VectorspaceName, Vectorspace>;

queries: Record<QueryName, Query>;
};
3 changes: 3 additions & 0 deletions helix-ts/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if (import.meta.main) {
console.log("it runs!");
}
Loading