File size: 5,098 Bytes
8484b88
 
 
4b2b8c3
 
8484b88
 
 
e356033
8484b88
 
 
 
 
 
 
 
 
 
 
f043058
 
 
 
8362db1
4beb684
8484b88
 
f043058
8484b88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d673ffd
8484b88
 
4b2b8c3
 
 
 
 
 
 
 
 
 
c44a2e6
7c36143
4b2b8c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8484b88
 
5877f28
8484b88
c79b68a
8484b88
4fea8bc
5913cb9
c79b68a
8484b88
 
aa08703
9adfcb4
 
 
 
 
7c627eb
9adfcb4
4c83da6
c484ceb
 
365af51
4c83da6
8484b88
 
 
 
c14ffd8
8484b88
 
 
 
c79b68a
8484b88
d360af7
8484b88
 
 
14f2c31
8484b88
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import os

import gradio as gr
from gradio.themes.base import Base
from gradio.themes.utils import colors, fonts, sizes
from transformers.utils import logging

from langchain_ollama import OllamaEmbeddings
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import Neo4jVector

logging.set_verbosity_info()
logger = logging.get_logger("transformers")

# Neo4jへの接続情報
NEO4J_URL = os.environ['NEO4J_URL']
NEO4J_USERNAME = os.environ['NEO4J_USERNAME']
NEO4J_PASSWORD = os.environ['NEO4J_PASSWORD']
NEO4J_DATABASE = os.environ['NEO4J_DATABASE']

# EMBEDDINGS = OllamaEmbeddings(
#    model="mxbai-embed-large",
# )

EMBEDDINGS = HuggingFaceEmbeddings(
    model_name="mixedbread-ai/mxbai-embed-large-v1"
)


def hybrid_search(input_text, top_k):

    # グラフからノード検索用インデックスを取得
    index = Neo4jVector.from_existing_graph(
        embedding=EMBEDDINGS,
        url=NEO4J_URL,
        username=NEO4J_USERNAME,
        password=NEO4J_PASSWORD,
        database=NEO4J_DATABASE,
        node_label="Document", # 検索対象ノード
        text_node_properties=["id", "text"], # 検索対象プロパティ
        embedding_node_property="embedding", # ベクトルデータの保存先プロパティ
        index_name="vector_index", # ベクトル検索用のインデックス名
        keyword_index_name="fulltext_index", # 全文検索用のインデックス名
        search_type="hybrid" # 検索タイプに「ハイブリッド」を設定(デフォルトは「ベクター」)
    )

    all_answers = []
    # クエリを設定して検索を実行
    query = input_text
    docs_with_score = index.similarity_search_with_score(query, k=top_k)
    for i in docs_with_score:
        doc, score = i
        all_answers.append(doc.metadata["source"])

    return "\n\n************************************************************\n\n".join(all_answers)


# カスタムテーマの作成
class CustomTheme(Base):
    def __init__(
        self,
        *,
        primary_hue: colors.Color | str = colors.blue,
        secondary_hue: colors.Color | str = colors.gray,
        neutral_hue: colors.Color | str = colors.gray,
        spacing_size: sizes.Size | str = sizes.spacing_md,
        radius_size: sizes.Size | str = sizes.radius_md,
        text_size: sizes.Size | str = sizes.text_lg,  # フォントサイズを大きく設定
        font: fonts.Font
        | str
        | list[fonts.Font | str] = (
            fonts.GoogleFont("IBM Plex Sans"),
            "Arial",
            "sans-serif",
        ),
        font_mono: fonts.Font
        | str
        | list[fonts.Font | str] = (
            fonts.GoogleFont("IBM Plex Mono"),
            "Courier",
            "monospace",
        ),
    ):
        super().__init__(
            primary_hue=primary_hue,
            secondary_hue=secondary_hue,
            neutral_hue=neutral_hue,
            spacing_size=spacing_size,
            radius_size=radius_size,
            text_size=text_size,
            font=font,
            font_mono=font_mono,
        )

# カスタムテーマの適用
theme = CustomTheme()

CSS ="""
.contain { display: flex; flex-direction: column; }
.gradio-container { min-height: 100vh !important; }
#component-0 { height: 100%; }
#textbox { flex-grow: 1; overflow: auto; resize: vertical;}
.secondary {background-color: #6366f1; }
#full-width-button { width: 100%; }
#search-result { overflow-y: scroll !important; font-size:18px !important; font-weight:500 !important;}
#question-box { font-size:18px !important; font-weight:500 !important; }
"""
#with gr.Blocks() as demo:
with gr.Blocks(theme=theme, css=CSS) as demo:
    with gr.Row():
        with gr.Column():
            gr.Markdown(f"""
                    ### ・非公式サイトです  
                    ### ・デモでしかないので速度・精度・動作は保証しないし新しい裁定にも対応しません。突然消す可能性もあり
                    ### ・ですます調で質問をすると精度が上がるかも\n\n
                    """)
            
    # スペースを追加
    with gr.Row():
        gr.Markdown("<br><br>", elem_id="spacer", visible=True)  # 改行タグを挿入してスペースを作成
    
    with gr.Row():
        gr.Markdown("# 裁定検索")
    with gr.Row():
        output = gr.TextArea(
            elem_id="search-result",
            label="検索結果",
        )
    with gr.Row():
        input = gr.Textbox(
            elem_id="question-box",
            label="質問",
            placeholder="カードを指定して破壊する能力でクリーチャーの下にあるカードを指定できますか",
            lines=3,
        )
    with gr.Row():
        submit = gr.Button(value="検索", variant="huggingface", elem_id="full-width-button")
        top_k = gr.Slider(1, 10, label="表示数", step=1, value=5, interactive=True)

    submit_click_event = submit.click(fn=hybrid_search, inputs=[input, top_k], outputs=output)

demo.launch()