import sys

sys.stdout.reconfigure(encoding="utf-8")
sys.stdin.reconfigure(encoding="utf-8")

import streamlit as st
import streamlit.components.v1 as components

import re

import random

CODE_BUILD_KG = """

# 准备 GraphStore

os.environ['NEBULA_USER'] = "root"
os.environ['NEBULA_PASSWORD'] = "nebula" # default password
os.environ['NEBULA_ADDRESS'] = "127.0.0.1:9669" # assumed we have NebulaGraph installed locally

space_name = "guardians"
edge_types, rel_prop_names = ["relationship"], ["relationship"] # default, could be omit if create from an empty kg
tags = ["entity"] # default, could be omit if create from an empty kg

graph_store = NebulaGraphStore(space_name=space_name, edge_types=edge_types, rel_prop_names=rel_prop_names, tags=tags)
storage_context = StorageContext.from_defaults(graph_store=graph_store)

# 从维基百科下载、预处理数据

from llama_index import download_loader

WikipediaReader = download_loader("WikipediaReader")

loader = WikipediaReader()

documents = loader.load_data(pages=['Guardians of the Galaxy Vol. 3'], auto_suggest=False)

# 利用 LLM 从文档中抽取知识三元组，并存储到 GraphStore（NebulaGraph）

kg_index = KnowledgeGraphIndex.from_documents(
    documents,
    storage_context=storage_context,
    max_triplets_per_chunk=10,
    service_context=service_context,
    space_name=space_name,
    edge_types=edge_types,
    rel_prop_names=rel_prop_names,
    tags=tags,
    include_embeddings=True,
)

"""

CODE_NL2CYPHER_LANGCHAIN = """
## Langchain
# Doc: https://python.langchain.com/docs/modules/chains/additional/graph_nebula_qa

from langchain.chat_models import ChatOpenAI
from langchain.chains import NebulaGraphQAChain
from langchain.graphs import NebulaGraph

graph = NebulaGraph(
    space=space_name,
    username="root",
    password="nebula",
    address="127.0.0.1",
    port=9669,
    session_pool_size=30,
)

chain = NebulaGraphQAChain.from_llm(
    llm, graph=graph, verbose=True
)

chain.run(
    "Tell me about Peter Quill?",
)
"""

CODE_NL2CYPHER_LLAMAINDEX = """

## Llama Index
# Doc: https://gpt-index.readthedocs.io/en/latest/examples/query_engine/knowledge_graph_query_engine.html

from llama_index.query_engine import KnowledgeGraphQueryEngine

from llama_index.storage.storage_context import StorageContext
from llama_index.graph_stores import NebulaGraphStore

nl2kg_query_engine = KnowledgeGraphQueryEngine(
    storage_context=storage_context,
    service_context=service_context,
    llm=llm,
    verbose=True,
)

response = nl2kg_query_engine.query(
    "Tell me about Peter Quill?",
)
"""


import os
import json
import openai
from llama_index.llms import AzureOpenAI
from langchain.embeddings import OpenAIEmbeddings
from llama_index import LangchainEmbedding
from llama_index import (
    VectorStoreIndex,
    SimpleDirectoryReader,
    KnowledgeGraphIndex,
    LLMPredictor,
    ServiceContext,
)

from llama_index.storage.storage_context import StorageContext
from llama_index.graph_stores import NebulaGraphStore

import logging
import sys

logging.basicConfig(
    stream=sys.stdout, level=logging.INFO
)  # logging.DEBUG for more verbose output
# logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))

openai.api_type = "azure"
openai.api_base = st.secrets["OPENAI_API_BASE"]
# openai.api_version = "2022-12-01" azure gpt-3
openai.api_version = "2023-05-15"  # azure gpt-3.5 turbo
openai.api_key = st.secrets["OPENAI_API_KEY"]

llm = AzureOpenAI(
    engine=st.secrets["DEPLOYMENT_NAME"],
    temperature=0,
    model="gpt-35-turbo",
)
llm_predictor = LLMPredictor(llm=llm)

# You need to deploy your own embedding model as well as your own chat completion model
embedding_llm = LangchainEmbedding(
    OpenAIEmbeddings(
        model="text-embedding-ada-002",
        deployment=st.secrets["EMBEDDING_DEPLOYMENT_NAME"],
        openai_api_key=openai.api_key,
        openai_api_base=openai.api_base,
        openai_api_type=openai.api_type,
        openai_api_version=openai.api_version,
    ),
    embed_batch_size=1,
)

service_context = ServiceContext.from_defaults(
    llm_predictor=llm_predictor,
    embed_model=embedding_llm,
)
os.environ["NEBULA_USER"] = st.secrets["graphd_user"]
os.environ["NEBULA_PASSWORD"] = st.secrets["graphd_password"]
os.environ[
    "NEBULA_ADDRESS"
] = f"{st.secrets['graphd_host']}:{st.secrets['graphd_port']}"

space_name = "guardians"
edge_types, rel_prop_names = ["relationship"], [
    "relationship"
]  # default, could be omit if create from an empty kg
tags = ["entity"]  # default, could be omit if create from an empty kg

graph_store = NebulaGraphStore(
    space_name=space_name,
    edge_types=edge_types,
    rel_prop_names=rel_prop_names,
    tags=tags,
)
storage_context = StorageContext.from_defaults(graph_store=graph_store)

from llama_index.query_engine import KnowledgeGraphQueryEngine

from llama_index.storage.storage_context import StorageContext
from llama_index.graph_stores import NebulaGraphStore

nl2kg_query_engine = KnowledgeGraphQueryEngine(
    storage_context=storage_context,
    service_context=service_context,
    llm=llm,
    verbose=True,
)


def cypher_to_all_paths(query):
    # Find the MATCH and RETURN parts
    match_parts = re.findall(r"(MATCH .+?(?=MATCH|$))", query, re.I | re.S)
    return_part = re.search(r"RETURN .+", query).group()

    modified_matches = []
    path_ids = []

    # Go through each MATCH part
    for i, part in enumerate(match_parts):
        path_id = f"path_{i}"
        path_ids.append(path_id)

        # Replace the MATCH keyword with "MATCH path_i = "
        modified_part = part.replace("MATCH ", f"MATCH {path_id} = ")
        modified_matches.append(modified_part)

    # Join the modified MATCH parts
    matches_string = " ".join(modified_matches)

    # Construct the new RETURN part
    return_string = f"RETURN {', '.join(path_ids)};"

    # Remove the old RETURN part from matches_string
    matches_string = matches_string.replace(return_part, "")

    # Combine everything
    modified_query = f"{matches_string}\n{return_string}"

    return modified_query


# write string to file
def result_to_df(result):
    from typing import Dict

    import pandas as pd

    columns = result.keys()
    d: Dict[str, list] = {}
    for col_num in range(result.col_size()):
        col_name = columns[col_num]
        col_list = result.column_values(col_name)
        d[col_name] = [x.cast() for x in col_list]
    return pd.DataFrame(d)


def render_pd_item(g, item):
    from nebula3.data.DataObject import Node, PathWrapper, Relationship

    if isinstance(item, Node):
        node_id = item.get_id().cast()
        tags = item.tags()  # list of strings
        props = dict()
        for tag in tags:
            props.update(item.properties(tag))
        g.add_node(node_id, label=node_id, title=str(props))
    elif isinstance(item, Relationship):
        src_id = item.start_vertex_id().cast()
        dst_id = item.end_vertex_id().cast()
        edge_name = item.edge_name()
        props = item.properties()
        # ensure start and end vertex exist in graph
        if not src_id in g.node_ids:
            g.add_node(src_id)
        if not dst_id in g.node_ids:
            g.add_node(dst_id)
        g.add_edge(src_id, dst_id, label=edge_name, title=str(props))
    elif isinstance(item, PathWrapper):
        for node in item.nodes():
            render_pd_item(g, node)
        for edge in item.relationships():
            render_pd_item(g, edge)
    elif isinstance(item, list):
        for it in item:
            render_pd_item(g, it)


def create_pyvis_graph(result_df):
    from pyvis.network import Network

    g = Network(
        notebook=True,
        directed=True,
        cdn_resources="in_line",
        height="500px",
        width="100%",
    )
    for _, row in result_df.iterrows():
        for item in row:
            render_pd_item(g, item)
    g.repulsion(
        node_distance=100,
        central_gravity=0.2,
        spring_length=200,
        spring_strength=0.05,
        damping=0.09,
    )
    return g


def query_nebulagraph(
    query,
    space_name=space_name,
    address=st.secrets["graphd_host"],
    port=9669,
    user=st.secrets["graphd_user"],
    password=st.secrets["graphd_password"],
):
    from nebula3.Config import SessionPoolConfig
    from nebula3.gclient.net.SessionPool import SessionPool

    config = SessionPoolConfig()
    session_pool = SessionPool(user, password, space_name, [(address, port)])
    session_pool.init(config)
    return session_pool.execute(query)


st.title("利用 LLM 构建、查询知识图谱")

(
    tab_code_kg,
    tab_notebook,
    tab_graph_view,
    tab_cypher,
    tab_nl2cypher,
    tab_code_nl2cypher,
) = st.tabs(
    [
        "代码:构建知识图谱",
        "完整 Notebook",
        "图谱可视化",
        "Cypher 查询",
        "自然语言查询",
        "代码:NL2Cypher",
    ]
)

with tab_code_kg:
    st.write("> 利用 LLM，几行代码构建知识图谱")
    st.code(body=CODE_BUILD_KG, language="python")

with tab_notebook:
    st.write("> 完整 Demo 过程 Notebook")
    st.write(
        """

这个 Notebook 展示了如何利用 LLM 从不同类型的信息源（以维基百科为例）中抽取知识三元组，并存储到图数据库 NebulaGraph 中。

本 Demo 中，我们先抽取了维基百科中关于《银河护卫队3》的信息，然后利用 LLM 生成的知识三元组，构建了一个图谱。
然后利用 Cypher 查询图谱，最后利用 LlamaIndex 和 Langchain 中的 NL2NebulaCypher，实现了自然语言查询图谱的功能。

您可以点击其他标签亲自试玩图谱的可视化、Cypher 查询、自然语言查询（NL2NebulaCypher）等功能。

             """
    )
    # link to download notebook
    st.markdown(
        """
这里可以[下载](https://www.siwei.io/demo-dumps/kg-llm/KG_Building.ipynb) 完整的 Notebook。
"""
    )

    components.iframe(
        src="https://www.siwei.io/demo-dumps/kg-llm/KG_Building.html",
        height=2000,
        width=800,
        scrolling=True,
    )

with tab_graph_view:
    st.write(
        "> 图谱的可视化部分采样，知识来源[银河护卫队3](https://en.wikipedia.org/wiki/Guardians_of_the_Galaxy_Vol._3)"
    )

    components.iframe(
        src="https://www.siwei.io/demo-dumps/kg-llm/nebulagraph_draw_sample.html",
        height=500,
        scrolling=True,
    )

with tab_cypher:
    st.write("> Cypher 查询图库")
    query_string = st.text_input(
        label="输入查询语句", value="MATCH ()-[e]->() RETURN e LIMIT 25"
    )
    if st.button("> 执行"):
        # run query
        result = query_nebulagraph(query_string)

        # convert to pandas dataframe
        result_df = result_to_df(result)

        # display pd dataframe
        st.dataframe(result_df)

        # create pyvis graph
        g = create_pyvis_graph(result_df)

        # render with random file name
        import random

        graph_html = g.generate_html(f"graph_{random.randint(0, 1000)}.html")

        components.html(graph_html, height=500, scrolling=True)

with tab_nl2cypher:
    st.write("> 使用自然语言查询图库")
    nl_query_string = st.text_input(
        label="输入自然语言问题", value="Tell me about Peter Quill?"
    )
    if st.button("生成 Cypher 查询语句，并执行"):
        response = nl2kg_query_engine.query(nl_query_string)
        graph_query = list(response.metadata.values())[0]["graph_store_query"]
        graph_query = graph_query.replace("WHERE", "\n  WHERE").replace(
            "RETURN", "\nRETURN"
        )
        answer = str(response)
        st.write(f"*答案*: {answer}")
        st.markdown(
            f"""
## 利用 LLM 生成的图查询语句
```cypher
{graph_query}
```
"""
        )
        st.write("## 结果可视化")
        render_query = cypher_to_all_paths(graph_query)
        result = query_nebulagraph(render_query)
        result_df = result_to_df(result)

        # create pyvis graph
        g = create_pyvis_graph(result_df)

        # render with random file name
        graph_html = g.generate_html(f"graph_{random.randint(0, 1000)}.html")

        components.html(graph_html, height=500, scrolling=True)


with tab_code_nl2cypher:
    st.write("利用 Langchain 或者 Llama Index，我们可以只用几行代码就实现自然语言查询图谱（NL2NebulaCypher）")

    tab_langchain, tab_llamaindex = st.tabs(["Langchain", "Llama Index"])
    with tab_langchain:
        st.code(body=CODE_NL2CYPHER_LANGCHAIN, language="python")
    with tab_llamaindex:
        st.code(body=CODE_NL2CYPHER_LLAMAINDEX, language="python")

    st.markdown(
        """

## 参考文档
                
- [Langchain: NebulaGraphQAChain](https://python.langchain.com/docs/modules/chains/additional/graph_nebula_qa)
- [Llama Index: KnowledgeGraphQueryEngine](https://gpt-index.readthedocs.io/en/latest/examples/query_engine/knowledge_graph_query_engine.html)
"""
    )

langchain.embeddings.OpenAIEmbeddings
[((12, 52), 'sys.stdout.reconfigure', 'sys.stdout.reconfigure', ([], {'encoding': '"""utf-8"""'}), "(encoding='utf-8')\n", (34, 52), False, 'import sys\n'), ((53, 92), 'sys.stdin.reconfigure', 'sys.stdin.reconfigure', ([], {'encoding': '"""utf-8"""'}), "(encoding='utf-8')\n", (74, 92), False, 'import sys\n'), ((2988, 3046), 'logging.basicConfig', 'logging.basicConfig', ([], {'stream': 'sys.stdout', 'level': 'logging.INFO'}), '(stream=sys.stdout, level=logging.INFO)\n', (3007, 3046), False, 'import logging\n'), ((3402, 3493), 'llama_index.llms.AzureOpenAI', 'AzureOpenAI', ([], {'engine': "st.secrets['DEPLOYMENT_NAME']", 'temperature': '(0)', 'model': '"""gpt-35-turbo"""'}), "(engine=st.secrets['DEPLOYMENT_NAME'], temperature=0, model=\n    'gpt-35-turbo')\n", (3413, 3493), False, 'from llama_index.llms import AzureOpenAI\n'), ((3520, 3541), 'llama_index.LLMPredictor', 'LLMPredictor', ([], {'llm': 'llm'}), '(llm=llm)\n', (3532, 3541), False, 'from llama_index import VectorStoreIndex, SimpleDirectoryReader, KnowledgeGraphIndex, LLMPredictor, ServiceContext\n'), ((4009, 4098), 'llama_index.ServiceContext.from_defaults', 'ServiceContext.from_defaults', ([], {'llm_predictor': 'llm_predictor', 'embed_model': 'embedding_llm'}), '(llm_predictor=llm_predictor, embed_model=\n    embedding_llm)\n', (4037, 4098), False, 'from llama_index import VectorStoreIndex, SimpleDirectoryReader, KnowledgeGraphIndex, LLMPredictor, ServiceContext\n'), ((4552, 4660), 'llama_index.graph_stores.NebulaGraphStore', 'NebulaGraphStore', ([], {'space_name': 'space_name', 'edge_types': 'edge_types', 'rel_prop_names': 'rel_prop_names', 'tags': 'tags'}), '(space_name=space_name, edge_types=edge_types,\n    rel_prop_names=rel_prop_names, tags=tags)\n', (4568, 4660), False, 'from llama_index.graph_stores import NebulaGraphStore\n'), ((4694, 4747), 'llama_index.storage.storage_context.StorageContext.from_defaults', 'StorageContext.from_defaults', ([], {'graph_store': 'graph_store'}), '(graph_store=graph_store)\n', (4722, 4747), False, 'from llama_index.storage.storage_context import StorageContext\n'), ((4952, 5071), 'llama_index.query_engine.KnowledgeGraphQueryEngine', 'KnowledgeGraphQueryEngine', ([], {'storage_context': 'storage_context', 'service_context': 'service_context', 'llm': 'llm', 'verbose': '(True)'}), '(storage_context=storage_context, service_context=\n    service_context, llm=llm, verbose=True)\n', (4977, 5071), False, 'from llama_index.query_engine import KnowledgeGraphQueryEngine\n'), ((8530, 8558), 'streamlit.title', 'st.title', (['"""利用 LLM 构建、查询知识图谱"""'], {}), "('利用 LLM 构建、查询知识图谱')\n", (8538, 8558), True, 'import streamlit as st\n'), ((8680, 8769), 'streamlit.tabs', 'st.tabs', (["['代码:构建知识图谱', '完整 Notebook', '图谱可视化', 'Cypher 查询', '自然语言查询', '代码:NL2Cypher']"], {}), "(['代码:构建知识图谱', '完整 Notebook', '图谱可视化', 'Cypher 查询', '自然语言查询',\n    '代码:NL2Cypher'])\n", (8687, 8769), True, 'import streamlit as st\n'), ((3671, 3920), 'langchain.embeddings.OpenAIEmbeddings', 'OpenAIEmbeddings', ([], {'model': '"""text-embedding-ada-002"""', 'deployment': "st.secrets['EMBEDDING_DEPLOYMENT_NAME']", 'openai_api_key': 'openai.api_key', 'openai_api_base': 'openai.api_base', 'openai_api_type': 'openai.api_type', 'openai_api_version': 'openai.api_version'}), "(model='text-embedding-ada-002', deployment=st.secrets[\n    'EMBEDDING_DEPLOYMENT_NAME'], openai_api_key=openai.api_key,\n    openai_api_base=openai.api_base, openai_api_type=openai.api_type,\n    openai_api_version=openai.api_version)\n", (3687, 3920), False, 'from langchain.embeddings import OpenAIEmbeddings\n'), ((5176, 5232), 're.findall', 're.findall', (['"""(MATCH .+?(?=MATCH|$))"""', 'query', '(re.I | re.S)'], {}), "('(MATCH .+?(?=MATCH|$))', query, re.I | re.S)\n", (5186, 5232), False, 'import re\n'), ((6408, 6423), 'pandas.DataFrame', 'pd.DataFrame', (['d'], {}), '(d)\n', (6420, 6423), True, 'import pandas as pd\n'), ((7626, 7723), 'pyvis.network.Network', 'Network', ([], {'notebook': '(True)', 'directed': '(True)', 'cdn_resources': '"""in_line"""', 'height': '"""500px"""', 'width': '"""100%"""'}), "(notebook=True, directed=True, cdn_resources='in_line', height=\n    '500px', width='100%')\n", (7633, 7723), False, 'from pyvis.network import Network\n'), ((8361, 8380), 'nebula3.Config.SessionPoolConfig', 'SessionPoolConfig', ([], {}), '()\n', (8378, 8380), False, 'from nebula3.Config import SessionPoolConfig\n'), ((8400, 8458), 'nebula3.gclient.net.SessionPool.SessionPool', 'SessionPool', (['user', 'password', 'space_name', '[(address, port)]'], {}), '(user, password, space_name, [(address, port)])\n', (8411, 8458), False, 'from nebula3.gclient.net.SessionPool import SessionPool\n'), ((8850, 8881), 'streamlit.write', 'st.write', (['"""> 利用 LLM，几行代码构建知识图谱"""'], {}), "('> 利用 LLM，几行代码构建知识图谱')\n", (8858, 8881), True, 'import streamlit as st\n'), ((8886, 8932), 'streamlit.code', 'st.code', ([], {'body': 'CODE_BUILD_KG', 'language': '"""python"""'}), "(body=CODE_BUILD_KG, language='python')\n", (8893, 8932), True, 'import streamlit as st\n'), ((8957, 8990), 'streamlit.write', 'st.write', (['"""> 完整 Demo 过程 Notebook"""'], {}), "('> 完整 Demo 过程 Notebook')\n", (8965, 8990), True, 'import streamlit as st\n'), ((8995, 9313), 'streamlit.write', 'st.write', (['"""\n\n这个 Notebook 展示了如何利用 LLM 从不同类型的信息源（以维基百科为例）中抽取知识三元组，并存储到图数据库 NebulaGraph 中。\n\n本 Demo 中，我们先抽取了维基百科中关于《银河护卫队3》的信息，然后利用 LLM 生成的知识三元组，构建了一个图谱。\n然后利用 Cypher 查询图谱，最后利用 LlamaIndex 和 Langchain 中的 NL2NebulaCypher，实现了自然语言查询图谱的功能。\n\n您可以点击其他标签亲自试玩图谱的可视化、Cypher 查询、自然语言查询（NL2NebulaCypher）等功能。\n\n             """'], {}), '(\n    """\n\n这个 Notebook 展示了如何利用 LLM 从不同类型的信息源（以维基百科为例）中抽取知识三元组，并存储到图数据库 NebulaGraph 中。\n\n本 Demo 中，我们先抽取了维基百科中关于《银河护卫队3》的信息，然后利用 LLM 生成的知识三元组，构建了一个图谱。\n然后利用 Cypher 查询图谱，最后利用 LlamaIndex 和 Langchain 中的 NL2NebulaCypher，实现了自然语言查询图谱的功能。\n\n您可以点击其他标签亲自试玩图谱的可视化、Cypher 查询、自然语言查询（NL2NebulaCypher）等功能。\n\n             """\n    )\n', (9003, 9313), True, 'import streamlit as st\n'), ((9354, 9465), 'streamlit.markdown', 'st.markdown', (['"""\n这里可以[下载](https://www.siwei.io/demo-dumps/kg-llm/KG_Building.ipynb) 完整的 Notebook。\n"""'], {}), '(\n    """\n这里可以[下载](https://www.siwei.io/demo-dumps/kg-llm/KG_Building.ipynb) 完整的 Notebook。\n"""\n    )\n', (9365, 9465), True, 'import streamlit as st\n'), ((9475, 9604), 'streamlit.components.v1.iframe', 'components.iframe', ([], {'src': '"""https://www.siwei.io/demo-dumps/kg-llm/KG_Building.html"""', 'height': '(2000)', 'width': '(800)', 'scrolling': '(True)'}), "(src=\n    'https://www.siwei.io/demo-dumps/kg-llm/KG_Building.html', height=2000,\n    width=800, scrolling=True)\n", (9492, 9604), True, 'import streamlit.components.v1 as components\n'), ((9661, 9770), 'streamlit.write', 'st.write', (['"""> 图谱的可视化部分采样，知识来源[银河护卫队3](https://en.wikipedia.org/wiki/Guardians_of_the_Galaxy_Vol._3)"""'], {}), "(\n    '> 图谱的可视化部分采样，知识来源[银河护卫队3](https://en.wikipedia.org/wiki/Guardians_of_the_Galaxy_Vol._3)'\n    )\n", (9669, 9770), True, 'import streamlit as st\n'), ((9780, 9909), 'streamlit.components.v1.iframe', 'components.iframe', ([], {'src': '"""https://www.siwei.io/demo-dumps/kg-llm/nebulagraph_draw_sample.html"""', 'height': '(500)', 'scrolling': '(True)'}), "(src=\n    'https://www.siwei.io/demo-dumps/kg-llm/nebulagraph_draw_sample.html',\n    height=500, scrolling=True)\n", (9797, 9909), True, 'import streamlit.components.v1 as components\n'), ((9954, 9979), 'streamlit.write', 'st.write', (['"""> Cypher 查询图库"""'], {}), "('> Cypher 查询图库')\n", (9962, 9979), True, 'import streamlit as st\n'), ((9999, 10072), 'streamlit.text_input', 'st.text_input', ([], {'label': '"""输入查询语句"""', 'value': '"""MATCH ()-[e]->() RETURN e LIMIT 25"""'}), "(label='输入查询语句', value='MATCH ()-[e]->() RETURN e LIMIT 25')\n", (10012, 10072), True, 'import streamlit as st\n'), ((10094, 10111), 'streamlit.button', 'st.button', (['"""> 执行"""'], {}), "('> 执行')\n", (10103, 10111), True, 'import streamlit as st\n'), ((10629, 10653), 'streamlit.write', 'st.write', (['"""> 使用自然语言查询图库"""'], {}), "('> 使用自然语言查询图库')\n", (10637, 10653), True, 'import streamlit as st\n'), ((10676, 10743), 'streamlit.text_input', 'st.text_input', ([], {'label': '"""输入自然语言问题"""', 'value': '"""Tell me about Peter Quill?"""'}), "(label='输入自然语言问题', value='Tell me about Peter Quill?')\n", (10689, 10743), True, 'import streamlit as st\n'), ((10765, 10796), 'streamlit.button', 'st.button', (['"""生成 Cypher 查询语句，并执行"""'], {}), "('生成 Cypher 查询语句，并执行')\n", (10774, 10796), True, 'import streamlit as st\n'), ((11681, 11759), 'streamlit.write', 'st.write', (['"""利用 Langchain 或者 Llama Index，我们可以只用几行代码就实现自然语言查询图谱（NL2NebulaCypher）"""'], {}), "('利用 Langchain 或者 Llama Index，我们可以只用几行代码就实现自然语言查询图谱（NL2NebulaCypher）')\n", (11689, 11759), True, 'import streamlit as st\n'), ((11797, 11834), 'streamlit.tabs', 'st.tabs', (["['Langchain', 'Llama Index']"], {}), "(['Langchain', 'Llama Index'])\n", (11804, 11834), True, 'import streamlit as st\n'), ((12022, 12332), 'streamlit.markdown', 'st.markdown', (['"""\n\n## 参考文档\n                \n- [Langchain: NebulaGraphQAChain](https://python.langchain.com/docs/modules/chains/additional/graph_nebula_qa)\n- [Llama Index: KnowledgeGraphQueryEngine](https://gpt-index.readthedocs.io/en/latest/examples/query_engine/knowledge_graph_query_engine.html)\n"""'], {}), '(\n    """\n\n## 参考文档\n                \n- [Langchain: NebulaGraphQAChain](https://python.langchain.com/docs/modules/chains/additional/graph_nebula_qa)\n- [Llama Index: KnowledgeGraphQueryEngine](https://gpt-index.readthedocs.io/en/latest/examples/query_engine/knowledge_graph_query_engine.html)\n"""\n    )\n', (12033, 12332), True, 'import streamlit as st\n'), ((10302, 10325), 'streamlit.dataframe', 'st.dataframe', (['result_df'], {}), '(result_df)\n', (10314, 10325), True, 'import streamlit as st\n'), ((10548, 10603), 'streamlit.components.v1.html', 'components.html', (['graph_html'], {'height': '(500)', 'scrolling': '(True)'}), '(graph_html, height=500, scrolling=True)\n', (10563, 10603), True, 'import streamlit.components.v1 as components\n'), ((11093, 11120), 'streamlit.write', 'st.write', (['f"""*答案*: {answer}"""'], {}), "(f'*答案*: {answer}')\n", (11101, 11120), True, 'import streamlit as st\n'), ((11129, 11197), 'streamlit.markdown', 'st.markdown', (['f"""\n## 利用 LLM 生成的图查询语句\n```cypher\n{graph_query}\n```\n"""'], {}), '(f"""\n## 利用 LLM 生成的图查询语句\n```cypher\n{graph_query}\n```\n""")\n', (11140, 11197), True, 'import streamlit as st\n'), ((11228, 11248), 'streamlit.write', 'st.write', (['"""## 结果可视化"""'], {}), "('## 结果可视化')\n", (11236, 11248), True, 'import streamlit as st\n'), ((11594, 11649), 'streamlit.components.v1.html', 'components.html', (['graph_html'], {'height': '(500)', 'scrolling': '(True)'}), '(graph_html, height=500, scrolling=True)\n', (11609, 11649), True, 'import streamlit.components.v1 as components\n'), ((11867, 11924), 'streamlit.code', 'st.code', ([], {'body': 'CODE_NL2CYPHER_LANGCHAIN', 'language': '"""python"""'}), "(body=CODE_NL2CYPHER_LANGCHAIN, language='python')\n", (11874, 11924), True, 'import streamlit as st\n'), ((11958, 12016), 'streamlit.code', 'st.code', ([], {'body': 'CODE_NL2CYPHER_LLAMAINDEX', 'language': '"""python"""'}), "(body=CODE_NL2CYPHER_LLAMAINDEX, language='python')\n", (11965, 12016), True, 'import streamlit as st\n'), ((5252, 5281), 're.search', 're.search', (['"""RETURN .+"""', 'query'], {}), "('RETURN .+', query)\n", (5261, 5281), False, 'import re\n'), ((10507, 10530), 'random.randint', 'random.randint', (['(0)', '(1000)'], {}), '(0, 1000)\n', (10521, 10530), False, 'import random\n'), ((11553, 11576), 'random.randint', 'random.randint', (['(0)', '(1000)'], {}), '(0, 1000)\n', (11567, 11576), False, 'import random\n')]