From b6f9c57d158ea3a7c2ab3aa2c957703c734efb54 Mon Sep 17 00:00:00 2001 From: Katarina Supe <61758502+katarinasupe@users.noreply.github.com> Date: Fri, 21 Jul 2023 10:13:46 +0200 Subject: [PATCH] Add LLM util docs (#939) * Add LLM util docs * Add small lang fixes * Update according to multiple labels fix in module * Update mage/templates/_mage_spells.mdx --------- Co-authored-by: Vlasta <95473291+vpavicic@users.noreply.github.com> --- .../python/llm-util/memgraph-lab-schema.png | Bin 0 -> 45917 bytes mage/query-modules/python/llm-util.md | 288 ++++++++++++++++++ mage/templates/_mage_spells.mdx | 1 + sidebars/sidebarsMAGE.js | 1 + 4 files changed, 290 insertions(+) create mode 100644 mage/data/query-modules/python/llm-util/memgraph-lab-schema.png create mode 100644 mage/query-modules/python/llm-util.md diff --git a/mage/data/query-modules/python/llm-util/memgraph-lab-schema.png b/mage/data/query-modules/python/llm-util/memgraph-lab-schema.png new file mode 100644 index 0000000000000000000000000000000000000000..c9346f019de09d817d8e85657b2ba2501eb9cd72 GIT binary patch literal 45917 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

T#+ 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 literal 0 HcmV?d00001 diff --git a/mage/query-modules/python/llm-util.md b/mage/query-modules/python/llm-util.md new file mode 100644 index 00000000000..d39053f5303 --- /dev/null +++ b/mage/query-modules/python/llm-util.md @@ -0,0 +1,288 @@ +--- +id: llm-util +title: llm_util +sidebar_label: llm_util +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import RunOnSubgraph from '../../templates/_run_on_subgraph.mdx'; + +export const Highlight = ({children, color}) => ( + + {children} + +); + + +[![docs-source](https://img.shields.io/badge/source-llm_util-FB6E00?logo=github&style=for-the-badge)](https://github.com/memgraph/mage/blob/main/python/json_util.py) + +| Trait | Value | +| ------------------- | ----------------------------------------------------- | +| **Module type** | **util** | +| **Implementation** | **Python** | +| **Parallelism** | **sequential** | + +## Procedures + + + +### schema(output_type) + +The `schema()` procedure generates the graph database schema in a **prompt-ready** or **raw** format. The prompt-ready format is optimized to describe the database schema in words best recognized by large language models (LLMs). The raw format offers all the necessary information about the graph schema in a format that can be customized for later use with LLMs. + +#### Input: + +* `output_type: str (default='prompt_ready')` ➡ By default, the graph schema will include additional context and it will be prompt-ready. If set to 'raw', it will produce a simpler version that can be adjusted for the prompt. + +#### Output: + +* `schema: mgp.Any` ➡ `str` containing prompt-ready graph schema description in a format suitable for large language models (LLMs), or `mgp.List` containing information on graph schema in raw format which can customized for LLMs. + +#### Usage: +Get **prompt-ready graph schema**: +```cypher +CALL llm_util.schema() YIELD schema RETURN schema; +``` +or +```cypher +CALL llm_util.schema('prompt_ready') YIELD schema RETURN schema; +``` + +Get **raw graph schema**: +```cypher +CALL llm_util.schema('raw') YIELD schema RETURN schema; +``` + +:::note +The `output_type` is case-insensitive. +::: + + +## Example - Get prompt-ready graph schema + + + + + Create a graph by running the following Cypher query: + + +```cypher +CREATE (n:Person {name: "Kate", age: 27})-[:IS_FRIENDS_WITH {since: "2023-06-21"}]->(m:Person:Student {name: "James", age: 30, year: "second"})-[:STUDIES_AT]->(:University {name: "University of Zagreb"}) CREATE (p:Person:Student {name: "Anthony", age: 25})-[:STUDIES_AT]->(:University {name: "University of Vienna"}) +WITH n, m +CREATE (n)-[:LIVES_IN]->(:City {name: "Zagreb"})<-[:LIVES_IN]-(m); +``` + + + +The schema of the created graph can be seen in Memgraph Lab, under the Graph Schema tab: + +

+ +
+ + + + + +Once the graph is created, run the following code to call the schema procedure: + + +```cypher +CALL llm_util.schema() YIELD schema RETURN schema; +``` + +or + +```cypher +CALL llm_util.schema('prompt_ready') YIELD schema RETURN schema; +``` + + + + + +Below is the result of running the schema procedure: + + +``` +Node properties are the following: +Node name: 'Person', Node properties: [{'property': 'name', 'type': 'str'}, {'property': 'age', 'type': 'int'}, {'property': 'year', 'type': 'str'}] +Node name: 'Student', Node properties: [{'property': 'name', 'type': 'str'}, {'property': 'age', 'type': 'int'}, {'property': 'year', 'type': 'str'}] +Node name: 'University', Node properties: [{'property': 'name', 'type': 'str'}] +Node name: 'City', Node properties: [{'property': 'name', 'type': 'str'}] + +Relationship properties are the following: +Relationship Name: 'IS_FRIENDS_WITH', Relationship Properties: [{'property': 'since', 'type': 'str'}] + +The relationships are the following: +['(:Person)-[:IS_FRIENDS_WITH]->(:Person)'] +['(:Person)-[:IS_FRIENDS_WITH]->(:Student)'] +['(:Person)-[:LIVES_IN]->(:City)'] +['(:Person)-[:STUDIES_AT]->(:University)'] +['(:Student)-[:STUDIES_AT]->(:University)'] +['(:Student)-[:LIVES_IN]->(:City)'] +``` + + + + + + + +## Example - Get raw graph schema + + + + + Create a graph by running the following Cypher query: + + +```cypher +CREATE (n:Person {name: "Kate", age: 27})-[:IS_FRIENDS_WITH {since: "2023-06-21"}]->(m:Person:Student {name: "James", age: 30, year: "second"})-[:STUDIES_AT]->(:University {name: "University of Zagreb"}) CREATE (p:Person:Student {name: "Anthony", age: 25})-[:STUDIES_AT]->(:University {name: "University of Vienna"}) +WITH n, m +CREATE (n)-[:LIVES_IN]->(:City {name: "Zagreb"})<-[:LIVES_IN]-(m); +``` + + + +The schema of the created graph can be seen in Memgraph Lab, under the Graph Schema tab: + +
+ +
+ +
+ + + +Once the graph is created, run the following code to call the schema procedure: + + +```cypher +CALL llm_util.schema('raw') YIELD schema RETURN schema; +``` + + + + + +Below is the result of running the schema procedure: + + +``` +{ + "node_props": { + "City": [ + { + "property": "name", + "type": "str" + } + ], + "Person": [ + { + "property": "name", + "type": "str" + }, + { + "property": "age", + "type": "int" + }, + { + "property": "year", + "type": "str" + } + ], + "Student": [ + { + "property": "name", + "type": "str" + }, + { + "property": "age", + "type": "int" + }, + { + "property": "year", + "type": "str" + } + ], + "University": [ + { + "property": "name", + "type": "str" + } + ] + }, + "rel_props": { + "IS_FRIENDS_WITH": [ + { + "property": "since", + "type": "str" + } + ] + }, + "relationships": [ + { + "end": "Person", + "start": "Person", + "type": "IS_FRIENDS_WITH" + }, + { + "end": "Student", + "start": "Person", + "type": "IS_FRIENDS_WITH" + }, + { + "end": "City", + "start": "Person", + "type": "LIVES_IN" + }, + { + "end": "University", + "start": "Person", + "type": "STUDIES_AT" + }, + { + "end": "University", + "start": "Student", + "type": "STUDIES_AT" + }, + { + "end": "City", + "start": "Student", + "type": "LIVES_IN" + } + ] +} +``` + + + + + +
diff --git a/mage/templates/_mage_spells.mdx b/mage/templates/_mage_spells.mdx index e429c89813c..89fa2bddaf4 100644 --- a/mage/templates/_mage_spells.mdx +++ b/mage/templates/_mage_spells.mdx @@ -54,6 +54,7 @@ | [graph_util](/mage/query-modules/cpp/graph-util) | C++ | A module with common graph algorithms and graph manipulation utilities | | [import_util](/mage/query-modules/python/import-util) | Python | A module for importing data from different formats (JSON). | | [json_util](/mage/query-modules/python/json-util) | Python | A module for loading JSON from a local file or remote address. | +| [llm_util](/mage/query-modules/python/llm-util) | Python | A module that contains procedures describing graphs in a format best suited for large language models (LLMs). | | [meta_util](/mage/query-modules/python/meta-util) | Python | A module that contains procedures describing graphs on a meta-level. | | [migrate](/mage/query-modules/python/migrate) | Python | A module that can access data from a MySQL, SQL Server or Oracle database. | | rust_example | Rust | Example of a basic module with input parameters forwarding, made in Rust. | diff --git a/sidebars/sidebarsMAGE.js b/sidebars/sidebarsMAGE.js index 4f2141e4d08..d00540faf7b 100644 --- a/sidebars/sidebarsMAGE.js +++ b/sidebars/sidebarsMAGE.js @@ -46,6 +46,7 @@ module.exports = { "query-modules/cpp/katz-centrality-online", "query-modules/python/kmeans", "query-modules/python/link-prediction-with-gnn", + "query-modules/python/llm-util", "query-modules/python/max-flow", "query-modules/python/meta-util", "query-modules/python/node-classification-with-gnn",