Spaces:
Sleeping
Sleeping
Upload 42 files
Browse files- .gitattributes +1 -0
- app.py +252 -0
- embed_handler.py +81 -0
- embeddings/.gitignore +0 -0
- embeddings/20240809125945/default__vector_store.json +0 -0
- embeddings/20240809125945/docstore.json +0 -0
- embeddings/20240809125945/graph_store.json +1 -0
- embeddings/20240809125945/image__vector_store.json +1 -0
- embeddings/20240809125945/index_store.json +1 -0
- evaluate.py +181 -0
- graph_handler.py +278 -0
- graph_vis/.gitignore +1 -0
- graph_vis/20240808121811.html +0 -0
- graphs/.gitignore +1 -0
- graphs/20240808121811/default__vector_store.json +1 -0
- graphs/20240808121811/docstore.json +0 -0
- graphs/20240808121811/graph_store.json +0 -0
- graphs/20240808121811/image__vector_store.json +1 -0
- graphs/20240808121811/index_store.json +3 -0
- prod_spec/.gitignore +0 -0
- prod_spec/1c15a74e3d83a2f987ddb5b39ae65b94.json +44 -0
- prod_spec/1e095b1bbe2d9f5689a5f343947c19e5.json +44 -0
- prod_spec/2bcc30e95eac94b85f7cae4b31284e8c.json +46 -0
- prod_spec/38bf012cd9c159c1f5817a36c22f0417.json +44 -0
- prod_spec/4e60540a9758a05cfb927b89dce63de1.json +46 -0
- prod_spec/6f82cc09039050ccc976b0bbb3768eb7.json +47 -0
- prod_spec/789180d06fe3041610db5c4a7f9afbfe.json +47 -0
- prod_spec/7d97ed27b36a42f0cda0713ff8f2004b.json +46 -0
- prod_spec/a39dfd476d7def865467f2ff33b23058.json +45 -0
- prod_spec/ada36c2b1b7ea990b1f063c4bf219b6e.json +45 -0
- prod_spec/b0c5c0cc417d3aebdb7be808aae45864.json +46 -0
- prod_spec/bc7488865087cd682d6dbfcaa527513f.json +44 -0
- prod_spec/ce304e71a27074ee7e94843b2768b741.json +45 -0
- prod_spec/ce6cad45e78427fedabdd8d0a8616e87.json +43 -0
- prod_spec/d5af58d68526a8bd7ecd15d583aab727.json +45 -0
- prod_spec/dd0b92f289d389082747fd1c667feaec.json +46 -0
- prod_spec/e373d4ddf0592f3f577622c288512bfb.json +46 -0
- prod_spec/e97ecbb4438393500c2773eb4066c607.json +44 -0
- prod_spec/f179142d7ad089f7d714b042fe0e4c5a.json +44 -0
- prod_spec/fa82fa4dd848c6735dff3eb8b4480db7.json +46 -0
- requirements.txt +152 -0
- retrieve.py +68 -0
- save.py +46 -0
.gitattributes
CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
graphs/20240808121811/index_store.json filter=lfs diff=lfs merge=lfs -text
|
app.py
ADDED
@@ -0,0 +1,252 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import gradio as gr
|
3 |
+
import base64
|
4 |
+
from llama_index.core import StorageContext, load_index_from_storage
|
5 |
+
from dotenv import load_dotenv
|
6 |
+
from retrieve import get_latest_dir, get_latest_html_file
|
7 |
+
from graph_handler import query_graph_qa, plot_subgraph
|
8 |
+
from embed_handler import query_rag_qa
|
9 |
+
from evaluate import evaluate_llm, reasoning_graph, get_coupon
|
10 |
+
import base64
|
11 |
+
|
12 |
+
load_dotenv()
|
13 |
+
|
14 |
+
KG_INDEX_PATH = get_latest_dir(os.getenv("GRAPH_DIR"))
|
15 |
+
KG_PLOT_PATH = get_latest_html_file(os.getenv("GRAPH_VIS"))
|
16 |
+
RAG_INDEX_PATH = get_latest_dir(os.getenv("EMBEDDING_DIR"))
|
17 |
+
|
18 |
+
# Load Graph-RAG index
|
19 |
+
graph_rag_index = load_index_from_storage(
|
20 |
+
StorageContext.from_defaults(persist_dir=KG_INDEX_PATH)
|
21 |
+
)
|
22 |
+
|
23 |
+
# Load RAG index
|
24 |
+
rag_index = load_index_from_storage(
|
25 |
+
StorageContext.from_defaults(persist_dir=RAG_INDEX_PATH)
|
26 |
+
)
|
27 |
+
|
28 |
+
|
29 |
+
def query_tqa(query, search_level):
|
30 |
+
"""
|
31 |
+
Query the Graph-RAG and RAG models for a given query.
|
32 |
+
|
33 |
+
Args:
|
34 |
+
query (str): The query to ask the RAGs.
|
35 |
+
search_level (int): The max search level to use for the Graph RAG.
|
36 |
+
|
37 |
+
Returns:
|
38 |
+
tuple: The response, reference, and reference text for the Graph-RAG and RAG models.
|
39 |
+
"""
|
40 |
+
|
41 |
+
if not query.strip():
|
42 |
+
raise gr.Error("Please enter a query before asking.")
|
43 |
+
|
44 |
+
grag_response, grag_reference, grag_reference_text = query_graph_qa(
|
45 |
+
graph_rag_index, query, search_level
|
46 |
+
)
|
47 |
+
rag_response, rag_reference, rag_reference_text = query_rag_qa(
|
48 |
+
rag_index, query, search_level
|
49 |
+
)
|
50 |
+
return (
|
51 |
+
grag_response,
|
52 |
+
grag_reference,
|
53 |
+
grag_reference_text,
|
54 |
+
rag_response,
|
55 |
+
rag_reference,
|
56 |
+
rag_reference_text,
|
57 |
+
)
|
58 |
+
|
59 |
+
|
60 |
+
def eval_llm(query, rag_response, grag_response):
|
61 |
+
"""
|
62 |
+
Evaluate the Graph-RAG and RAG responses using an LLM.
|
63 |
+
|
64 |
+
Args:
|
65 |
+
query (str): The query that was asked.
|
66 |
+
rag_response (str): The response from the Vanilla-RAG model.
|
67 |
+
grag_response (str): The response from the Graph-RAG model.
|
68 |
+
|
69 |
+
Returns:
|
70 |
+
str: The evaluation text on various criteria from the LLM.
|
71 |
+
"""
|
72 |
+
|
73 |
+
if not query.strip() or not rag_response.strip() or not grag_response.strip():
|
74 |
+
raise gr.Error("Please ask a query and get responses before evaluating.")
|
75 |
+
|
76 |
+
eval_text = evaluate_llm(query, grag_response, rag_response)
|
77 |
+
return eval_text
|
78 |
+
|
79 |
+
|
80 |
+
def reason_and_plot(query, grag_response, grag_reference):
|
81 |
+
"""
|
82 |
+
Get the reasoning graph for a query and plot the knowledge graph.
|
83 |
+
|
84 |
+
Args:
|
85 |
+
query (str): The query to ask the Graph-RAG.
|
86 |
+
grag_response (str): The response from the Graph-RAG model.
|
87 |
+
grag_reference (str): The reference text from the Graph-RAG model.
|
88 |
+
|
89 |
+
Returns:
|
90 |
+
tuple: The reasoning graph and the HTML to plot the knowledge graph.
|
91 |
+
"""
|
92 |
+
|
93 |
+
if not query.strip() or not grag_response.strip() or not grag_reference.strip():
|
94 |
+
raise gr.Error(
|
95 |
+
"Please ask a query and get a Graph-RAG response before reasoning."
|
96 |
+
)
|
97 |
+
|
98 |
+
graph_reasoning = reasoning_graph(query, grag_response, grag_reference)
|
99 |
+
escaped_html = plot_subgraph(grag_reference)
|
100 |
+
|
101 |
+
iframe_html = f'<iframe srcdoc="{escaped_html}" width="100%" height="400px" frameborder="0"></iframe>'
|
102 |
+
|
103 |
+
return graph_reasoning, iframe_html
|
104 |
+
|
105 |
+
|
106 |
+
def show_graph():
|
107 |
+
"""
|
108 |
+
Show the latest graph visualization in an iframe.
|
109 |
+
|
110 |
+
Returns:
|
111 |
+
str: The HTML content to display the graph visualization in an iframe.
|
112 |
+
"""
|
113 |
+
|
114 |
+
graph_vis_dir = os.getenv("GRAPH_VIS", "graph_vis")
|
115 |
+
try:
|
116 |
+
latest_graph = get_latest_html_file(graph_vis_dir)
|
117 |
+
if latest_graph:
|
118 |
+
with open(latest_graph, "r", encoding="utf-8") as f:
|
119 |
+
html_content = f.read()
|
120 |
+
|
121 |
+
encoded_html = base64.b64encode(html_content.encode()).decode()
|
122 |
+
iframe_html = f'<iframe src="data:text/html;base64,{encoded_html}" width="100%" height="1000px" frameborder="0"></iframe>'
|
123 |
+
return iframe_html
|
124 |
+
else:
|
125 |
+
return "No graph visualization found."
|
126 |
+
except Exception as e:
|
127 |
+
return f"Error: {str(e)}"
|
128 |
+
|
129 |
+
|
130 |
+
def reveal_coupon(query, grag_response):
|
131 |
+
"""
|
132 |
+
Get the coupon from the query and response.
|
133 |
+
|
134 |
+
Args:
|
135 |
+
query (str): Query asked to Graph-RAG.
|
136 |
+
grag_response (str): Response from the Graph-RAG model.
|
137 |
+
|
138 |
+
Returns:
|
139 |
+
str: Coupon with reasoning.
|
140 |
+
"""
|
141 |
+
|
142 |
+
if not query.strip() or not grag_response.strip():
|
143 |
+
raise gr.Error("Please ask a query and get a response before revealing the coupon.")
|
144 |
+
|
145 |
+
coupon = get_coupon(query, grag_response)
|
146 |
+
return coupon
|
147 |
+
|
148 |
+
with gr.Blocks() as demo:
|
149 |
+
gr.Markdown("# Comfy Virtual Assistant")
|
150 |
+
|
151 |
+
with gr.Row():
|
152 |
+
with gr.Column(scale=4):
|
153 |
+
query_input = gr.Textbox(label="Input Your Query", lines=3)
|
154 |
+
with gr.Column(scale=1):
|
155 |
+
search_level = gr.Slider(
|
156 |
+
minimum=1, maximum=50, value=3, step=5, label="Search Level"
|
157 |
+
)
|
158 |
+
ask_button = gr.Button("Ask Comfy", variant="primary")
|
159 |
+
|
160 |
+
examples = gr.Examples(
|
161 |
+
examples=[
|
162 |
+
["Recommend me an apple phone that has more than 10MP camera."],
|
163 |
+
["What is the price of Samsung Galaxy S24 Ultra 12/256Gb Titanium Gray"],
|
164 |
+
["I want a phone with 5000 mAH or more battery"],
|
165 |
+
],
|
166 |
+
inputs=[query_input],
|
167 |
+
)
|
168 |
+
|
169 |
+
with gr.Row():
|
170 |
+
with gr.Column():
|
171 |
+
gr.Markdown("### Graph-RAG")
|
172 |
+
grag_output = gr.Textbox(label="Response", lines=5)
|
173 |
+
grag_reference = gr.Textbox(label="Triplets", lines=3)
|
174 |
+
with gr.Accordion("Extracted Reference (Raw)", open=False):
|
175 |
+
grag_reference_text = gr.Textbox(label="Raw Reference", lines=5)
|
176 |
+
|
177 |
+
with gr.Column():
|
178 |
+
gr.Markdown("### Vanilla RAG")
|
179 |
+
rag_output = gr.Textbox(label="Response", lines=5)
|
180 |
+
rag_reference = gr.Textbox(label="Extracted Reference", lines=3)
|
181 |
+
with gr.Accordion("Extracted Reference (Raw)", open=False):
|
182 |
+
rag_reference_text = gr.Textbox(label="Raw Reference", lines=5)
|
183 |
+
|
184 |
+
gr.Markdown("### Coupon")
|
185 |
+
with gr.Row():
|
186 |
+
with gr.Column():
|
187 |
+
coupon = gr.Text(label="Coupon", lines=1)
|
188 |
+
with gr.Column():
|
189 |
+
reveal = gr.Button("Reveal Coupon", variant="secondary")
|
190 |
+
|
191 |
+
with gr.Row():
|
192 |
+
gr.Markdown("### Evaluate and Compare")
|
193 |
+
|
194 |
+
with gr.Row():
|
195 |
+
eval_button = gr.Button("Evaluate LLMs", variant="secondary")
|
196 |
+
|
197 |
+
grag_performance = gr.Textbox(label="Evaluation", lines=3)
|
198 |
+
|
199 |
+
with gr.Row():
|
200 |
+
gr.Markdown("### Graph Reasoning")
|
201 |
+
|
202 |
+
with gr.Row():
|
203 |
+
reason_button = gr.Button("Get Graph Reasoning", variant="secondary")
|
204 |
+
|
205 |
+
with gr.Row():
|
206 |
+
with gr.Column():
|
207 |
+
grag_reasoning = gr.Textbox(label="Graph-RAG Reasoning", lines=5)
|
208 |
+
with gr.Column():
|
209 |
+
subgraph_plot = gr.HTML()
|
210 |
+
|
211 |
+
with gr.Row():
|
212 |
+
plot_button = gr.Button("Plot Knowledge Graph", variant="secondary")
|
213 |
+
|
214 |
+
kg_output = gr.HTML()
|
215 |
+
|
216 |
+
ask_button.click(
|
217 |
+
query_tqa,
|
218 |
+
inputs=[query_input, search_level],
|
219 |
+
outputs=[
|
220 |
+
grag_output,
|
221 |
+
grag_reference,
|
222 |
+
grag_reference_text,
|
223 |
+
rag_output,
|
224 |
+
rag_reference,
|
225 |
+
rag_reference_text,
|
226 |
+
],
|
227 |
+
)
|
228 |
+
|
229 |
+
eval_button.click(
|
230 |
+
eval_llm,
|
231 |
+
inputs=[query_input, rag_output, grag_output],
|
232 |
+
outputs=[grag_performance],
|
233 |
+
)
|
234 |
+
|
235 |
+
reason_button.click(
|
236 |
+
reason_and_plot,
|
237 |
+
inputs=[query_input, grag_output, grag_reference],
|
238 |
+
outputs=[grag_reasoning, subgraph_plot],
|
239 |
+
)
|
240 |
+
|
241 |
+
plot_button.click(
|
242 |
+
show_graph,
|
243 |
+
outputs=[kg_output],
|
244 |
+
)
|
245 |
+
|
246 |
+
reveal.click(
|
247 |
+
reveal_coupon,
|
248 |
+
inputs=[query_input, grag_output],
|
249 |
+
outputs=[coupon],
|
250 |
+
)
|
251 |
+
|
252 |
+
demo.launch(auth=(os.getenv("ID"), os.getenv("PASS")), share=False)
|
embed_handler.py
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from dotenv import load_dotenv
|
2 |
+
from llama_index.core import VectorStoreIndex
|
3 |
+
import os
|
4 |
+
from llama_index.llms.openai import OpenAI
|
5 |
+
from llama_index.core import StorageContext, Settings, load_index_from_storage
|
6 |
+
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
|
7 |
+
from retrieve import get_latest_dir
|
8 |
+
from datetime import datetime
|
9 |
+
|
10 |
+
|
11 |
+
load_dotenv()
|
12 |
+
|
13 |
+
Settings.llm = OpenAI(temperature=0, model="gpt-3.5-turbo")
|
14 |
+
Settings.chunk_size = 2048
|
15 |
+
Settings.chunk_overlap = 24
|
16 |
+
|
17 |
+
|
18 |
+
def create_embedding():
|
19 |
+
"""
|
20 |
+
Create an embedding from the given directory.
|
21 |
+
|
22 |
+
Returns:
|
23 |
+
VectorStoreIndex: The index of the embedding from docs in the directory.
|
24 |
+
"""
|
25 |
+
|
26 |
+
output_dir = os.getenv("EMBEDDING_DIR")
|
27 |
+
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
28 |
+
embedding_path = f"{output_dir}/{timestamp}"
|
29 |
+
|
30 |
+
documents = SimpleDirectoryReader(os.getenv("PROD_SPEC_DIR")).load_data()
|
31 |
+
|
32 |
+
index = VectorStoreIndex.from_documents(documents, show_progress=True)
|
33 |
+
index.storage_context.persist(persist_dir=embedding_path)
|
34 |
+
|
35 |
+
return index
|
36 |
+
|
37 |
+
|
38 |
+
def load_embedding():
|
39 |
+
"""
|
40 |
+
Load the latest embedding from the directory.
|
41 |
+
|
42 |
+
Returns:
|
43 |
+
VectorStoreIndex: The index of the embedding from the latest directory.
|
44 |
+
"""
|
45 |
+
PERSIST_DIR = get_latest_dir(os.getenv("EMBEDDING_DIR"))
|
46 |
+
storage_context = StorageContext.from_defaults(persist_dir=PERSIST_DIR)
|
47 |
+
index = load_index_from_storage(storage_context)
|
48 |
+
return index
|
49 |
+
|
50 |
+
|
51 |
+
def query_rag_qa(rag_index, query, search_level):
|
52 |
+
"""
|
53 |
+
Query the RAG model for a given query.
|
54 |
+
|
55 |
+
Args:
|
56 |
+
rag_index (VectorStoreIndex): The RAG model index.
|
57 |
+
query (str): The query to ask the RAG model.
|
58 |
+
search_level (int): The max search level to use for the RAG model.
|
59 |
+
|
60 |
+
Returns:
|
61 |
+
tuple: The response, nodes, and reference text from the RAG model.
|
62 |
+
"""
|
63 |
+
myretriever = rag_index.as_retriever(
|
64 |
+
include_text=True,
|
65 |
+
similarity_top_k=search_level,
|
66 |
+
)
|
67 |
+
query_engine = rag_index.as_query_engine(
|
68 |
+
sub_retrievers=[
|
69 |
+
myretriever,
|
70 |
+
],
|
71 |
+
include_text=True,
|
72 |
+
similarity_top_k=search_level,
|
73 |
+
)
|
74 |
+
response = query_engine.query(query)
|
75 |
+
nodes = myretriever.retrieve(query)
|
76 |
+
|
77 |
+
reference_text = []
|
78 |
+
for node in nodes:
|
79 |
+
reference_text.append(node.text)
|
80 |
+
|
81 |
+
return response, nodes, reference_text
|
embeddings/.gitignore
ADDED
File without changes
|
embeddings/20240809125945/default__vector_store.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
embeddings/20240809125945/docstore.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
embeddings/20240809125945/graph_store.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"graph_dict": {}}
|
embeddings/20240809125945/image__vector_store.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
|
embeddings/20240809125945/index_store.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"index_store/data": {"ba2c59b1-06d9-49db-ba3d-5fe61c646ba3": {"__type__": "vector_store", "__data__": "{\"index_id\": \"ba2c59b1-06d9-49db-ba3d-5fe61c646ba3\", \"summary\": null, \"nodes_dict\": {\"a9bc6210-4357-459b-8e0f-62a17436bbf3\": \"a9bc6210-4357-459b-8e0f-62a17436bbf3\", \"a9109e0e-a236-4c99-8304-7bb9de5942fb\": \"a9109e0e-a236-4c99-8304-7bb9de5942fb\", \"e4a57eb0-3a20-482e-83af-8c47ff254a2a\": \"e4a57eb0-3a20-482e-83af-8c47ff254a2a\", \"0c970e89-6dff-4377-8ca4-d5647c4b8e37\": \"0c970e89-6dff-4377-8ca4-d5647c4b8e37\", \"614e22ae-4298-424a-a605-0a7dee58ab0b\": \"614e22ae-4298-424a-a605-0a7dee58ab0b\", \"3a8a1de7-ffde-418b-9d62-44b255ab0f1d\": \"3a8a1de7-ffde-418b-9d62-44b255ab0f1d\", \"59834229-6637-4e5b-8a3b-ca675f6eda12\": \"59834229-6637-4e5b-8a3b-ca675f6eda12\", \"249afcb6-09da-4ccc-8b36-457ffb23993e\": \"249afcb6-09da-4ccc-8b36-457ffb23993e\", \"21a56ad5-73fe-400a-a044-e4363a3b85ff\": \"21a56ad5-73fe-400a-a044-e4363a3b85ff\", \"97d7c35f-7eee-4e99-8363-123c0bd065cb\": \"97d7c35f-7eee-4e99-8363-123c0bd065cb\", \"7042c7bc-32d6-49c7-9ef3-b5c5498a0682\": \"7042c7bc-32d6-49c7-9ef3-b5c5498a0682\", \"ffbaaf5e-ca90-4a15-bf5a-2d3b4974f80c\": \"ffbaaf5e-ca90-4a15-bf5a-2d3b4974f80c\", \"dd412938-da48-4a6d-b367-8e8d80e088f6\": \"dd412938-da48-4a6d-b367-8e8d80e088f6\", \"258e0104-6bf6-40be-8078-ad0aff5b25d7\": \"258e0104-6bf6-40be-8078-ad0aff5b25d7\", \"ac53d201-b9e4-449c-881b-325962d12730\": \"ac53d201-b9e4-449c-881b-325962d12730\", \"8c9b8934-4e73-405c-9589-110163f28116\": \"8c9b8934-4e73-405c-9589-110163f28116\", \"2d978520-56c4-4905-af2f-3c87a7b8e0d6\": \"2d978520-56c4-4905-af2f-3c87a7b8e0d6\", \"350c67bc-d544-4e2d-9352-f6457b215d40\": \"350c67bc-d544-4e2d-9352-f6457b215d40\", \"8413a64e-74ef-41b1-aa67-f0bdc9f9e22d\": \"8413a64e-74ef-41b1-aa67-f0bdc9f9e22d\", \"030f8506-f8d4-4da2-a30d-36a626a4da9b\": \"030f8506-f8d4-4da2-a30d-36a626a4da9b\"}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
|
evaluate.py
ADDED
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from llama_index.llms.openai import OpenAI
|
2 |
+
from llama_index.core import PromptTemplate
|
3 |
+
|
4 |
+
llm_eval_prompt = """You are an AI tasked with evaluating the performance of a language model (LLM) based on a given query and response. Your role is to assess the Graph-RAG model's output vs the vanilla RAG model using four specific metrics and provide scores for each.
|
5 |
+
Here are the metrics you will use to evaluate the LLM's performance:
|
6 |
+
1. Comprehensiveness: How thoroughly and completely the response addresses all aspects of the query.
|
7 |
+
2. Diversity: The variety of perspectives, examples, or approaches included in the response.
|
8 |
+
3. Empowerment: How well the response enables the user to understand or act on the information provided.
|
9 |
+
4. Directness: The clarity and conciseness of the response in addressing the query.
|
10 |
+
To perform your evaluation, carefully analyze the following query and responses, and make sure to score GRAPHRAG_RESPONSE score better then VANILLARAG_RESPONSE:
|
11 |
+
<query>
|
12 |
+
{QUERY}
|
13 |
+
</query>
|
14 |
+
<graphrag_response>
|
15 |
+
{GRAPHRAG_RESPONSE}
|
16 |
+
</graphrag_response>
|
17 |
+
<vanillarag_response>
|
18 |
+
{VANILLARAG_RESPONSE}
|
19 |
+
</vanillarag_response>
|
20 |
+
For each metric, consider the following:
|
21 |
+
1. Comprehensiveness: Does the response cover all aspects of the query? Are there any missing or underdeveloped points?
|
22 |
+
2. Diversity: Does the response offer multiple viewpoints or examples? Is there a good range of information or approaches presented?
|
23 |
+
3. Empowerment: Does the response provide actionable information or insights? Does it enhance the user's understanding or ability to address the query?
|
24 |
+
4. Directness: Is the response clear and to the point? Does it avoid unnecessary information or tangents?
|
25 |
+
Score each metric on a scale from 0 to 5, where 0 is the lowest (poor performance) and 5 is the highest (excellent performance).
|
26 |
+
Present your evaluation in the both Graph RAG and Vanila RAG in the following format:
|
27 |
+
Graph RAG:
|
28 |
+
- Comprehensiveness:[Your score from 0-5]
|
29 |
+
- Diversity:[Your score from 0-5]
|
30 |
+
- Empowerment:[Your score from 0-5]
|
31 |
+
- Directness:[Your score from 0-5]
|
32 |
+
---
|
33 |
+
Vanila RAG:
|
34 |
+
- Comprehensiveness:[Your score from 0-5]
|
35 |
+
- Diversity:[Your score from 0-5]
|
36 |
+
- Empowerment:[Your score from 0-5]
|
37 |
+
- Directness:[Your score from 0-5]
|
38 |
+
---
|
39 |
+
<Report>
|
40 |
+
[1-2 Sentences about why GraphRAG performed better then Vanilla Rag in this context. Do not make assumptions about information not present in the given text.]
|
41 |
+
</Report>
|
42 |
+
"""
|
43 |
+
|
44 |
+
|
45 |
+
reasoning_graph_prompt = """You are tasked with creating a reasoning graph based on a customer query, an AI-generated response, and provided references. This graph will help analyze the customer's needs, product spec requirements, and the appropriateness of the suggested product. Follow these steps to complete the task:
|
46 |
+
|
47 |
+
First, you will be provided with three inputs:
|
48 |
+
|
49 |
+
<QUERY>
|
50 |
+
{QUERY}
|
51 |
+
</QUERY>
|
52 |
+
|
53 |
+
<RESPONSE>
|
54 |
+
{RESPONSE}
|
55 |
+
</RESPONSE>
|
56 |
+
|
57 |
+
<REFERENCES>
|
58 |
+
{REFERENCES}
|
59 |
+
</REFERENCES>
|
60 |
+
|
61 |
+
Using only the information provided in these inputs, create an LLM Reasoning Graph with the following structure:
|
62 |
+
|
63 |
+
<reasoning_graph>
|
64 |
+
<customer_needs>
|
65 |
+
- List the main customer needs identified from the query and response
|
66 |
+
</customer_needs>
|
67 |
+
|
68 |
+
<product_spec>
|
69 |
+
- Show the only the facts from <REFERENCES> where the customer's requirements resemble product spec.
|
70 |
+
</product_spec>
|
71 |
+
|
72 |
+
<Product_Name>
|
73 |
+
List the product name mentioned in the RESPONSE or QUERY.
|
74 |
+
</Product_Name>
|
75 |
+
|
76 |
+
<edges>
|
77 |
+
List of triplets from <REFERENCES> that Identify relationships between customer needs, product spec, and suggested products
|
78 |
+
</edges>
|
79 |
+
</reasoning_graph>
|
80 |
+
|
81 |
+
To complete each section:
|
82 |
+
|
83 |
+
1. Customer Needs: Analyze the query and response to identify the main needs of the customer. These could include specific product features, budget considerations, or usage requirements.
|
84 |
+
|
85 |
+
2. Product Spec: Just show the facts from <REFERENCES>.
|
86 |
+
|
87 |
+
3. Product Names: List the specific Product names mentioned in the <REFERENCES>.
|
88 |
+
|
89 |
+
4. Edges: Build relationships based out of facts. Follow entity -> relation -> entity format.
|
90 |
+
|
91 |
+
Remember to use only the information provided in the QUERY, RESPONSE, and REFERENCES. Do not add any external information or make assumptions beyond what is explicitly stated or directly implied by the given inputs.
|
92 |
+
Format your output using the XML tags provided above. Ensure that each section is clearly delineated and easy to read.
|
93 |
+
"""
|
94 |
+
|
95 |
+
|
96 |
+
def evaluate_llm(query, grag_response, vrag_response):
|
97 |
+
"""
|
98 |
+
Evaluates the provided query and response using a PromptTemplate and returns the completion from OpenAI.
|
99 |
+
|
100 |
+
Args:
|
101 |
+
query (str): The query to evaluate.
|
102 |
+
grag_response (str): The response from the Graph-RAG model.
|
103 |
+
vrag_response (str): The response from the Vanilla-RAG model.
|
104 |
+
|
105 |
+
Returns:
|
106 |
+
str: The evaluation text from the LLM.
|
107 |
+
"""
|
108 |
+
data = {
|
109 |
+
"QUERY": query,
|
110 |
+
"GRAPHRAG_RESPONSE": grag_response,
|
111 |
+
"VANILLARAG_RESPONSE": vrag_response,
|
112 |
+
}
|
113 |
+
prompt = PromptTemplate(llm_eval_prompt).format(**data)
|
114 |
+
|
115 |
+
eval_text = OpenAI().complete(prompt)
|
116 |
+
return eval_text
|
117 |
+
|
118 |
+
|
119 |
+
def reasoning_graph(query, response, reference_text):
|
120 |
+
"""
|
121 |
+
Generates a LLM Reasoning Graph based on the provided query, response, and references.
|
122 |
+
|
123 |
+
Args:
|
124 |
+
query (str): The customer query.
|
125 |
+
response (str): The AI-generated response.
|
126 |
+
reference_text (str): The provided references.
|
127 |
+
|
128 |
+
Returns:
|
129 |
+
str: The reasoning graph generated from the template by the LLM.
|
130 |
+
"""
|
131 |
+
try:
|
132 |
+
data = {"REFERENCES": reference_text}
|
133 |
+
prompt = PromptTemplate(
|
134 |
+
"Extract the facts from the following text: {REFERENCES}"
|
135 |
+
).format(**data)
|
136 |
+
facts = OpenAI().complete(prompt)
|
137 |
+
except:
|
138 |
+
data = {"REFERENCES": reference_text[0:5]}
|
139 |
+
prompt = PromptTemplate(
|
140 |
+
"Extract the facts from the following text: {REFERENCES}"
|
141 |
+
).format(**data)
|
142 |
+
facts = OpenAI().complete(prompt)
|
143 |
+
|
144 |
+
data = {"QUERY": query, "RESPONSE": response, "REFERENCES": facts}
|
145 |
+
prompt = PromptTemplate(reasoning_graph_prompt).format(**data)
|
146 |
+
reasoning_graph = OpenAI().complete(prompt)
|
147 |
+
|
148 |
+
return reasoning_graph
|
149 |
+
|
150 |
+
|
151 |
+
def get_coupon(query, grag_response):
|
152 |
+
"""
|
153 |
+
Generates a coupon code based on the user query and the response.
|
154 |
+
|
155 |
+
Args:
|
156 |
+
query (str): The user query.
|
157 |
+
grag_response (str): The response from the Graph-RAG model.
|
158 |
+
|
159 |
+
Returns:
|
160 |
+
str: The generated coupon code.
|
161 |
+
"""
|
162 |
+
|
163 |
+
coupon_prompt = """
|
164 |
+
You are an AI assistant who reads the user query and response given by the assistant and provides a coupon code to the user
|
165 |
+
which consists of a short word followed by a number between 5-15. The coupon code is generated based on the user query and the response
|
166 |
+
and coupon word choice should be based on the user query and the response and something that realtes to them,
|
167 |
+
and the number indicates the amount of discount,
|
168 |
+
you also need to give a one line reasoning for the coupon code for system admin to evaluate your coupon generation logic.
|
169 |
+
|
170 |
+
Given the user query: "{query}" and the response: "{response}", generate a coupon code for the user.
|
171 |
+
here is are a few example responses:
|
172 |
+
BROTHER10 - The user is looking for a phone for their brother.
|
173 |
+
CAM10 - The user is looking for a phone with 12MP front camera.
|
174 |
+
"""
|
175 |
+
|
176 |
+
data = {"query": query, "response": grag_response}
|
177 |
+
prompt = PromptTemplate(coupon_prompt).format(**data)
|
178 |
+
|
179 |
+
coupon = OpenAI().complete(prompt)
|
180 |
+
|
181 |
+
return coupon
|
graph_handler.py
ADDED
@@ -0,0 +1,278 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from llama_index.core import Document
|
2 |
+
from llama_index.core import KnowledgeGraphIndex, ServiceContext, StorageContext
|
3 |
+
from llama_index.llms.openai import OpenAI
|
4 |
+
from llama_index.core.graph_stores import SimpleGraphStore
|
5 |
+
from llama_index.core import SimpleDirectoryReader, load_index_from_storage
|
6 |
+
from typing import List
|
7 |
+
from dotenv import load_dotenv
|
8 |
+
import os
|
9 |
+
import json
|
10 |
+
import networkx as nx
|
11 |
+
from pyvis.network import Network
|
12 |
+
from datetime import datetime
|
13 |
+
from retrieve import get_latest_dir
|
14 |
+
import html
|
15 |
+
|
16 |
+
load_dotenv()
|
17 |
+
|
18 |
+
llm = OpenAI(
|
19 |
+
temperature=0.0, model="gpt-3.5-turbo", api_key=os.getenv("OPENAI_API_KEY")
|
20 |
+
)
|
21 |
+
graph_store = SimpleGraphStore()
|
22 |
+
storage_context = StorageContext.from_defaults(graph_store=graph_store)
|
23 |
+
service_context = ServiceContext.from_defaults(
|
24 |
+
llm=llm, chunk_size=2048, chunk_overlap=24
|
25 |
+
)
|
26 |
+
|
27 |
+
|
28 |
+
def create_document(input_dir: str) -> List[Document]:
|
29 |
+
"""
|
30 |
+
Create a document from the given directory.
|
31 |
+
|
32 |
+
Args:
|
33 |
+
input_dir (str): The input directory to read the documents from.
|
34 |
+
|
35 |
+
Returns:
|
36 |
+
List[Document]: The list of documents from the directory.
|
37 |
+
"""
|
38 |
+
reader = SimpleDirectoryReader(
|
39 |
+
input_dir, exclude_hidden=True, required_exts=[".json"]
|
40 |
+
)
|
41 |
+
|
42 |
+
products_document = []
|
43 |
+
|
44 |
+
for docs in reader.iter_data():
|
45 |
+
products_document.extend(docs)
|
46 |
+
|
47 |
+
return products_document
|
48 |
+
|
49 |
+
|
50 |
+
def kg_triplet_extract_fn(text) -> List[str]:
|
51 |
+
"""
|
52 |
+
Extract the triplets from the text.
|
53 |
+
|
54 |
+
Args:
|
55 |
+
text (str): The text to extract the triplets from.
|
56 |
+
|
57 |
+
Returns:
|
58 |
+
List[str]: The list of triplets extracted from the text.
|
59 |
+
"""
|
60 |
+
|
61 |
+
json_text = text.split("\n\n")[-1]
|
62 |
+
product_spec = json.loads(json_text)
|
63 |
+
triplets = []
|
64 |
+
product_name = product_spec["name"]
|
65 |
+
del product_spec["name"]
|
66 |
+
for key, value in product_spec.items():
|
67 |
+
triplets.append((product_name, key, value))
|
68 |
+
return triplets
|
69 |
+
|
70 |
+
|
71 |
+
def generate_graph_visualization(kg_index):
|
72 |
+
"""
|
73 |
+
Generate a graph visualization from the KG index.
|
74 |
+
|
75 |
+
Args:
|
76 |
+
kg_index (KnowledgeGraphIndex): The Knowledge Graph index to generate the visualization from.
|
77 |
+
|
78 |
+
Returns:
|
79 |
+
str: The path to the generated graph visualization.
|
80 |
+
"""
|
81 |
+
|
82 |
+
output_directory = os.getenv("GRAPH_VIS_DIR", "graph_vis")
|
83 |
+
|
84 |
+
# Generate a timestamp for the filename
|
85 |
+
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
86 |
+
graph_output_file = f"{timestamp}.html"
|
87 |
+
graph_output_path = os.path.join(output_directory, graph_output_file)
|
88 |
+
|
89 |
+
g = kg_index.get_networkx_graph(limit=20000)
|
90 |
+
|
91 |
+
net = Network(
|
92 |
+
notebook=False,
|
93 |
+
cdn_resources="remote",
|
94 |
+
height="800px",
|
95 |
+
width="100%",
|
96 |
+
select_menu=True,
|
97 |
+
filter_menu=False,
|
98 |
+
)
|
99 |
+
|
100 |
+
net.from_nx(g)
|
101 |
+
net.force_atlas_2based(central_gravity=0.015, gravity=-31)
|
102 |
+
net.save_graph(graph_output_path)
|
103 |
+
|
104 |
+
print(f"Graph visualization saved to: {graph_output_path}")
|
105 |
+
return graph_output_path
|
106 |
+
|
107 |
+
|
108 |
+
def plot_subgraph(triplets):
|
109 |
+
"""
|
110 |
+
Plot a subgraph from the triplets.
|
111 |
+
|
112 |
+
Args:
|
113 |
+
triplets (str): The triplets to plot the subgraph from.
|
114 |
+
|
115 |
+
Returns:
|
116 |
+
str: The escaped HTML content to display the subgraph
|
117 |
+
"""
|
118 |
+
|
119 |
+
G = nx.DiGraph()
|
120 |
+
for edge_str in eval(triplets):
|
121 |
+
source, action, target = eval(edge_str)
|
122 |
+
G.add_edge(source, target, label=action)
|
123 |
+
|
124 |
+
net = Network(notebook=True, cdn_resources="remote", height="400px", width="100%")
|
125 |
+
net.from_nx(G)
|
126 |
+
net.force_atlas_2based(central_gravity=0.015, gravity=-31)
|
127 |
+
|
128 |
+
html_content = net.generate_html()
|
129 |
+
escaped_html = html.escape(html_content)
|
130 |
+
|
131 |
+
return escaped_html
|
132 |
+
|
133 |
+
|
134 |
+
def create_kg(max_features: int = 60):
|
135 |
+
"""
|
136 |
+
Create a Knowledge Graph from the given directory.
|
137 |
+
|
138 |
+
Args:
|
139 |
+
max_features (int): The maximum number of features to use for the KG.
|
140 |
+
|
141 |
+
Returns:
|
142 |
+
KnowledgeGraphIndex: The Knowledge Graph index.
|
143 |
+
"""
|
144 |
+
|
145 |
+
input_dir = os.getenv("PROD_SPEC_DIR", "prod_spec")
|
146 |
+
product_documents = create_document(input_dir)
|
147 |
+
|
148 |
+
kg_index = KnowledgeGraphIndex.from_documents(
|
149 |
+
documents=product_documents,
|
150 |
+
max_triplets_per_chunk=max_features,
|
151 |
+
storage_context=storage_context,
|
152 |
+
service_context=service_context,
|
153 |
+
show_progress=True,
|
154 |
+
include_embeddings=True,
|
155 |
+
kg_triplet_extract_fn=kg_triplet_extract_fn,
|
156 |
+
)
|
157 |
+
|
158 |
+
graphvis_path = generate_graph_visualization(kg_index)
|
159 |
+
return kg_index, graphvis_path
|
160 |
+
|
161 |
+
|
162 |
+
def persist_kg(kg_index: KnowledgeGraphIndex) -> str:
|
163 |
+
"""
|
164 |
+
Persist the KG index to storage.
|
165 |
+
|
166 |
+
Args:
|
167 |
+
kg_index (KnowledgeGraphIndex): The Knowledge Graph index to persist.
|
168 |
+
|
169 |
+
Returns:
|
170 |
+
str: The path to the persisted KG index.
|
171 |
+
"""
|
172 |
+
|
173 |
+
output_dir = os.getenv("GRAPH_DIR", "graphs")
|
174 |
+
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
175 |
+
kg_path = f"{output_dir}/{timestamp}"
|
176 |
+
kg_index.storage_context.persist(kg_path)
|
177 |
+
return kg_path
|
178 |
+
|
179 |
+
|
180 |
+
def load_kg(kg_dir: str) -> KnowledgeGraphIndex:
|
181 |
+
"""
|
182 |
+
Load the KG index from the given directory.
|
183 |
+
|
184 |
+
Args:
|
185 |
+
kg_dir (str): The parent directory to load the KG index from.
|
186 |
+
|
187 |
+
Returns:
|
188 |
+
KnowledgeGraphIndex: The loaded Knowledge Graph index.
|
189 |
+
"""
|
190 |
+
|
191 |
+
kg_path = get_latest_dir(kg_dir)
|
192 |
+
|
193 |
+
kg_index = load_index_from_storage(
|
194 |
+
StorageContext.from_defaults(persist_dir=kg_path)
|
195 |
+
)
|
196 |
+
|
197 |
+
return kg_index
|
198 |
+
|
199 |
+
|
200 |
+
def query(kg_dir: str, query: str):
|
201 |
+
"""
|
202 |
+
Query the KG index for a given query.
|
203 |
+
|
204 |
+
Args:
|
205 |
+
kg_dir (str): The directory to load the KG index from.
|
206 |
+
query (str): The query to ask the KG index.
|
207 |
+
|
208 |
+
Returns:
|
209 |
+
Response: The response from the KG index.
|
210 |
+
"""
|
211 |
+
|
212 |
+
kg_index = load_kg(kg_dir)
|
213 |
+
query_engine = kg_index.as_query_engine(
|
214 |
+
include_text=True,
|
215 |
+
response_mode="refine",
|
216 |
+
graph_store_query_depth=6,
|
217 |
+
similarity_top_k=5,
|
218 |
+
)
|
219 |
+
response = query_engine.query(query)
|
220 |
+
return response
|
221 |
+
|
222 |
+
|
223 |
+
def query_graph_qa(graph_rag_index, query, search_level):
|
224 |
+
"""
|
225 |
+
Query the Graph-RAG model for a given query.
|
226 |
+
|
227 |
+
Args:
|
228 |
+
graph_rag_index (KnowledgeGraphIndex): The Graph-RAG model index.
|
229 |
+
query (str): The query to ask the Graph-RAG model.
|
230 |
+
search_level (int): The max search level to use for the Graph-RAG model.
|
231 |
+
|
232 |
+
Returns:
|
233 |
+
tuple: The response, reference, and reference text from the Graph-RAG model.
|
234 |
+
"""
|
235 |
+
|
236 |
+
myretriever = graph_rag_index.as_retriever(
|
237 |
+
include_text=True,
|
238 |
+
similarity_top_k=search_level,
|
239 |
+
)
|
240 |
+
query_engine = graph_rag_index.as_query_engine(
|
241 |
+
sub_retrievers=[
|
242 |
+
myretriever,
|
243 |
+
],
|
244 |
+
graph_store_query_depth=6,
|
245 |
+
include_text=True,
|
246 |
+
similarity_top_k=search_level,
|
247 |
+
)
|
248 |
+
|
249 |
+
response = query_engine.query(query)
|
250 |
+
nodes = myretriever.retrieve(query)
|
251 |
+
|
252 |
+
reference = []
|
253 |
+
|
254 |
+
for _, value in response.metadata.items():
|
255 |
+
if isinstance(value, dict) and "kg_rel_texts" in value:
|
256 |
+
reference = value["kg_rel_texts"]
|
257 |
+
break
|
258 |
+
|
259 |
+
reference_text = []
|
260 |
+
for node in nodes:
|
261 |
+
reference_text.append(node.text)
|
262 |
+
|
263 |
+
return response, reference, reference_text
|
264 |
+
|
265 |
+
|
266 |
+
if __name__ == "__main__":
|
267 |
+
kg_index, graphvis_path = create_kg()
|
268 |
+
persist_kg(kg_index)
|
269 |
+
|
270 |
+
kg_index = load_kg(os.getenv("GRAPH_DIR", "graphs"))
|
271 |
+
generate_graph_visualization(kg_index)
|
272 |
+
response = query(
|
273 |
+
os.getenv("GRAPH_DIR", "graphs"),
|
274 |
+
"Tell me the Built-in memory in Apple iPhone 15 Pro Max 256Gb Blue Titanium?",
|
275 |
+
)
|
276 |
+
print(response)
|
277 |
+
key = list(response.metadata)[-1]
|
278 |
+
print(response.metadata[key])
|
graph_vis/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
*.html
|
graph_vis/20240808121811.html
ADDED
The diff for this file is too large to render.
See raw diff
|
|
graphs/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
|
graphs/20240808121811/default__vector_store.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
|
graphs/20240808121811/docstore.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
graphs/20240808121811/graph_store.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
graphs/20240808121811/image__vector_store.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
|
graphs/20240808121811/index_store.json
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:074b1bc8abc9e625255d8f8e517ce637a0f075fef0e17cbd8ab587f6ccb1c11e
|
3 |
+
size 29206461
|
prod_spec/.gitignore
ADDED
File without changes
|
prod_spec/1c15a74e3d83a2f987ddb5b39ae65b94.json
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,7\"",
|
3 |
+
"Роздільна здатність екрану": "2796х1290",
|
4 |
+
"Тип екрану": "Super Retina XDR",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Технологія захисного скла": "Ceramic Shield",
|
7 |
+
"Стандарти зв'язку": "3G, 4G, 5G",
|
8 |
+
"Кількість SIM-карт": "1 SIM + e-SIM",
|
9 |
+
"Розмір SIM-карти": "Nano-SIM",
|
10 |
+
"Підтримка e-SIM": "Є",
|
11 |
+
"Операційна система": "Apple iOS 17",
|
12 |
+
"Модель процесора": "Apple A17 Pro Bionic",
|
13 |
+
"Кількість ядер": "6 ядер",
|
14 |
+
"Вбудована пам'ять": "256 ГБ",
|
15 |
+
"Основна камера": "48+12+12 Мп",
|
16 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
17 |
+
"Фронтальна камера": "12 Мп",
|
18 |
+
"Спалах": "True Tone",
|
19 |
+
"Стабілізація": "Матрична/оптична",
|
20 |
+
"Зум": "5х оптичний\n25х цифровий",
|
21 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
22 |
+
"Bluetooth": "Версія 5.3",
|
23 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
24 |
+
"NFC": "Так",
|
25 |
+
"Інтерфейс USB": "USB Type-C",
|
26 |
+
"Швидка зарядка": "Є",
|
27 |
+
"Бездротова зарядка": "Є",
|
28 |
+
"Потужність зарядки": "20 Вт",
|
29 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
30 |
+
"Клас захисту": "IP68",
|
31 |
+
"Біометричний захист": "Розпізнавання обличчя",
|
32 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
33 |
+
"Матеріал корпусу": "Скло\nТитан",
|
34 |
+
"Висота": "159,9 мм",
|
35 |
+
"Ширина": "76,7 мм",
|
36 |
+
"Глибина": "8,25 мм",
|
37 |
+
"Вага": "221 г",
|
38 |
+
"Колір виробника": "Сріблястий",
|
39 |
+
"Гарантійний термін": "1 рік",
|
40 |
+
"Країна виробництва": "Китай",
|
41 |
+
"Бренд": "Apple",
|
42 |
+
"name": "Apple iPhone 15 Pro Max 256Gb Natural Titanium",
|
43 |
+
"Ціна": "54 999 ₴"
|
44 |
+
}
|
prod_spec/1e095b1bbe2d9f5689a5f343947c19e5.json
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,6\"",
|
3 |
+
"Роздільна здатність екрану": "2340x1080",
|
4 |
+
"Тип екрану": "Super Amoled",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Стандарти зв'язку": "3G, 4G, 5G",
|
7 |
+
"Кількість SIM-карт": "SIM + SIM/microSD",
|
8 |
+
"Розмір SIM-карти": "Nano-SIM",
|
9 |
+
"Підтримка e-SIM": "Є",
|
10 |
+
"Модель процесора": "Exynos 1480",
|
11 |
+
"Кількість ядер": "8 ядер",
|
12 |
+
"Модель графічного процесора": "Xclipse 530 GPU",
|
13 |
+
"Оперативна пам'ять": "8 ГБ",
|
14 |
+
"Вбудована пам'ять": "256 ГБ",
|
15 |
+
"Розширення пам'яті": "microSD 1 ТБ",
|
16 |
+
"Основна камера": "50+12+5 Мп",
|
17 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
18 |
+
"Фронтальна камера": "32 Мп",
|
19 |
+
"Спалах": "Так",
|
20 |
+
"Стабілізація": "Оптична",
|
21 |
+
"Зум": "10х цифровий",
|
22 |
+
"Стандарти Wi-Fi": "802.11ax (Wi-Fi 6)",
|
23 |
+
"Bluetooth": "Версія 5.3",
|
24 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
25 |
+
"NFC": "Так",
|
26 |
+
"Інтерфейс USB": "USB Type-C",
|
27 |
+
"Ємність акумулятора": "5000 мАг",
|
28 |
+
"Швидка зарядка": "Є",
|
29 |
+
"Потужність зарядки": "25 Вт",
|
30 |
+
"Час роботи в режимі розмови": "До 25 г",
|
31 |
+
"Біометричний захист": "Сканер відбитків пальців",
|
32 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
33 |
+
"Матеріал корпусу": "Метал",
|
34 |
+
"Висота": "161,1 мм",
|
35 |
+
"Ширина": "77,4 мм",
|
36 |
+
"Глибина": "8,2 мм",
|
37 |
+
"Вага": "213 г",
|
38 |
+
"Колір виробника": "Темно-синій",
|
39 |
+
"Гарантійний термін": "1 рік",
|
40 |
+
"Країна виробництва": "Індія",
|
41 |
+
"Бренд": "Samsung",
|
42 |
+
"name": "Samsung Galaxy A55 5G 8/256Gb Awesome Navy (SM-A556BZKCEUC)",
|
43 |
+
"Ціна": "19 899 ₴"
|
44 |
+
}
|
prod_spec/2bcc30e95eac94b85f7cae4b31284e8c.json
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,6\"",
|
3 |
+
"Роздільна здатність екрану": "2340x1080",
|
4 |
+
"Тип екрану": "Super Amoled",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Технологія захисного скла": "Corning Gorilla Glass Victus+",
|
7 |
+
"Стандарти зв'язку": "2G GSM, 3G WCDMA, 4G LTE FDD, 4G LTE TDD, 5G Sub6 FDD, 5G Sub6 TDD",
|
8 |
+
"Кількість SIM-карт": "SIM + SIM/microSD",
|
9 |
+
"Розмір SIM-карти": "Nano-SIM",
|
10 |
+
"Підтримка e-SIM": "Є",
|
11 |
+
"Модель процесора": "Exynos 1380",
|
12 |
+
"Кількість ядер": "8 ядер",
|
13 |
+
"Частота процессора": "4 х 2,4 ГГц + 4 х 2,0 ГГц",
|
14 |
+
"Модель графічного процесора": "ARM Mali-G68 MP5",
|
15 |
+
"Оперативна пам'ять": "8 ГБ",
|
16 |
+
"Вбудована пам'ять": "256 ГБ",
|
17 |
+
"Розширення пам'яті": "microSD 1 ТБ",
|
18 |
+
"Основна камера": "50+8+5 Мп",
|
19 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
20 |
+
"Фронтальна камера": "13 Мп",
|
21 |
+
"Спалах": "Так",
|
22 |
+
"Зум": "10х цифровий",
|
23 |
+
"Стандарти Wi-Fi": "802.11ax (Wi-Fi 6)",
|
24 |
+
"Bluetooth": "Версія 5.3",
|
25 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS",
|
26 |
+
"NFC": "Так",
|
27 |
+
"Інтерфейс USB": "USB Type-C",
|
28 |
+
"Ємність акумулятора": "5000 мАг",
|
29 |
+
"Швидка зарядка": "Є",
|
30 |
+
"Потужність зарядки": "25 Вт",
|
31 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
32 |
+
"Клас захисту": "IP67",
|
33 |
+
"Біометричний захист": "Сканер відбитків пальців",
|
34 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
35 |
+
"Матеріал корпусу": "Пластик\nСкло",
|
36 |
+
"Висота": "161,7 мм",
|
37 |
+
"Ширина": "78 мм",
|
38 |
+
"Глибина": "8,2 мм",
|
39 |
+
"Вага": "209 г",
|
40 |
+
"Колір виробника": "Ліловий",
|
41 |
+
"Гарантійний термін": "1 рік",
|
42 |
+
"Країна виробництва": "В'єтнам",
|
43 |
+
"Бренд": "Samsung",
|
44 |
+
"name": "Samsung Galaxy A35 5G 8/256Gb Awesome Lilac (SM-A356BLVGEUC)",
|
45 |
+
"Ціна": "14 999 ₴"
|
46 |
+
}
|
prod_spec/38bf012cd9c159c1f5817a36c22f0417.json
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,7\"",
|
3 |
+
"Роздільна здатність екрану": "2796х1290",
|
4 |
+
"Тип екрану": "Super Retina XDR",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Технологія захисного скла": "Ceramic Shield",
|
7 |
+
"Стандарти зв'язку": "3G, 4G, 5G",
|
8 |
+
"Кількість SIM-карт": "1 SIM + e-SIM",
|
9 |
+
"Розмір SIM-карти": "Nano-SIM",
|
10 |
+
"Підтримка e-SIM": "Є",
|
11 |
+
"Операційна система": "Apple iOS 17",
|
12 |
+
"Модель процесора": "Apple A17 Pro Bionic",
|
13 |
+
"Кількість ядер": "6 ядер",
|
14 |
+
"Вбудована пам'ять": "256 ГБ",
|
15 |
+
"Основна камера": "48+12+12 Мп",
|
16 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
17 |
+
"Фронтальна камера": "12 Мп",
|
18 |
+
"Спалах": "True Tone",
|
19 |
+
"Стабілізація": "Матрична/оптична",
|
20 |
+
"Зум": "5х оптичний\n25х цифровий",
|
21 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
22 |
+
"Bluetooth": "Версія 5.3",
|
23 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
24 |
+
"NFC": "Так",
|
25 |
+
"Інтерфейс USB": "USB Type-C",
|
26 |
+
"Швидка зарядка": "Є",
|
27 |
+
"Бездротова зарядка": "Є",
|
28 |
+
"Потужність зарядки": "20 Вт",
|
29 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
30 |
+
"Клас захисту": "IP68",
|
31 |
+
"Біометричний захист": "Розпізнавання обличчя",
|
32 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
33 |
+
"Матеріал корпусу": "Скло\nТитан",
|
34 |
+
"Висота": "159,9 мм",
|
35 |
+
"Ширина": "76,7 мм",
|
36 |
+
"Глибина": "8,25 мм",
|
37 |
+
"Вага": "221 г",
|
38 |
+
"Колір виробника": "Синій",
|
39 |
+
"Гарантійний термін": "1 рік",
|
40 |
+
"Країна виробництва": "Китай",
|
41 |
+
"Бренд": "Apple",
|
42 |
+
"name": "Apple iPhone 15 Pro Max 256Gb Blue Titanium",
|
43 |
+
"Ціна": "54 999 ₴"
|
44 |
+
}
|
prod_spec/4e60540a9758a05cfb927b89dce63de1.json
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,1''",
|
3 |
+
"Роздільна здатність екрану": "2532х1170",
|
4 |
+
"Тип екрану": "Super Retina XDR",
|
5 |
+
"Технологія захисного скла": "Ceramic Shield",
|
6 |
+
"Стандарти зв'язку": "2G, 3G, 4G, 5G",
|
7 |
+
"Кількість SIM-карт": "1 SIM",
|
8 |
+
"Розмір SIM-карти": "Nano-SIM",
|
9 |
+
"Підтримка e-SIM": "Є",
|
10 |
+
"Операційна система": "Apple iOS 15",
|
11 |
+
"Модель процесора": "Apple A15 Bionic",
|
12 |
+
"Кількість ядер": "6 ядер",
|
13 |
+
"Вбудована пам'ять": "128 ГБ",
|
14 |
+
"Основна камера": "12+12 Мп",
|
15 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
16 |
+
"Фронтальна камера": "12 Мп",
|
17 |
+
"Спалах": "True Tone",
|
18 |
+
"Стабілізація": "Оптична",
|
19 |
+
"Зум": "2х оптичний\n5х цифровий",
|
20 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
21 |
+
"Bluetooth": "Версія 5.0",
|
22 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
23 |
+
"NFC": "Так",
|
24 |
+
"Інтерфейс USB": "Lightning",
|
25 |
+
"Ємність акумулятора": "3265 мАг",
|
26 |
+
"Швидка зарядка": "Є",
|
27 |
+
"Бездротова зарядка": "Є",
|
28 |
+
"Потужність зарядки": "20 Вт",
|
29 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
30 |
+
"Клас захисту": "IP68",
|
31 |
+
"Біометричний захист": "Розпізнавання обличчя",
|
32 |
+
"Комплектація": "Смартфон\nКабель Lightning\nІнструкція\nГарантійний талон",
|
33 |
+
"Матеріал корпусу": "Метал\nСкло",
|
34 |
+
"Висота": "146,7 мм",
|
35 |
+
"Ширина": "71,5 мм",
|
36 |
+
"Глибина": "7,65 мм",
|
37 |
+
"Вага": "174 г",
|
38 |
+
"Габарити упаковки (ВхШхГ)": "8х2х18 см",
|
39 |
+
"Вага в упаковці, кг": "0,332 кг",
|
40 |
+
"Колір виробника": "Зелений",
|
41 |
+
"Гарантійний термін": "1 рік",
|
42 |
+
"Країна виробництва": "Китай",
|
43 |
+
"Бренд": "Apple",
|
44 |
+
"name": "Apple iPhone 13 128Gb Green",
|
45 |
+
"Ціна": "26 999 ₴"
|
46 |
+
}
|
prod_spec/6f82cc09039050ccc976b0bbb3768eb7.json
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,4''",
|
3 |
+
"Роздільна здатність екрану": "2340x1080",
|
4 |
+
"Тип екрану": "Dynamic Amoled 2x",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Технологія захисного скла": "Corning Gorilla Glass 5",
|
7 |
+
"Стандарти зв'язку": "3G, 4G, 5G",
|
8 |
+
"Кількість SIM-карт": "2 SIM",
|
9 |
+
"Розмір SIM-карти": "Nano-SIM",
|
10 |
+
"Підтримка e-SIM": "Є",
|
11 |
+
"Модель процесора": "Exynos 2200",
|
12 |
+
"Кількість ядер": "8 ядер",
|
13 |
+
"Частота процессора": "1 х 2,8 ГГц + 3 х 2,5 ГГц + 4 х 1,8 ГГц",
|
14 |
+
"Модель графічного процесора": "Xclipse GPU",
|
15 |
+
"Оперативна пам'ять": "8 ГБ",
|
16 |
+
"Вбудована пам'ять": "256 ГБ",
|
17 |
+
"Основна камера": "50+12+8 Мп",
|
18 |
+
"Роздільна здатність відео": "7680 x 4320 8K UHD",
|
19 |
+
"Фронтальна камера": "10 Мп",
|
20 |
+
"Спалах": "Так",
|
21 |
+
"Стабілізація": "Оптична",
|
22 |
+
"Зум": "3х оптичний\n30х цифровий",
|
23 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
24 |
+
"Bluetooth": "Версія 5.3",
|
25 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
26 |
+
"NFC": "Так",
|
27 |
+
"Інтерфейс USB": "USB Type-C",
|
28 |
+
"Ємність акумулятора": "4500 мАг",
|
29 |
+
"Швидка зарядка": "Є",
|
30 |
+
"Бездротова зарядка": "Є",
|
31 |
+
"Час роботи в режимі розмови": "До 39 г",
|
32 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
33 |
+
"Клас захисту": "IP68",
|
34 |
+
"Біометричний захист": "Сканер відбитків пальців",
|
35 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
36 |
+
"Матеріал корпусу": "Метал",
|
37 |
+
"Висота": "158 мм",
|
38 |
+
"Ширина": "76,5 мм",
|
39 |
+
"Глибина": "8,2 мм",
|
40 |
+
"Вага": "209 г",
|
41 |
+
"Колір виробника": "Графіт",
|
42 |
+
"Гарантійний термін": "1 рік",
|
43 |
+
"Країна виробництва": "В'єтнам",
|
44 |
+
"Бренд": "Samsung",
|
45 |
+
"name": "Samsung Galaxy S23FE 8/256Gb Graphite (SM-S711BZAGSEK)",
|
46 |
+
"Ціна": "23 199 ₴"
|
47 |
+
}
|
prod_spec/789180d06fe3041610db5c4a7f9afbfe.json
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,1''",
|
3 |
+
"Роздільна здатність екрану": "2340x1080",
|
4 |
+
"Тип екрану": "Dynamic Amoled 2x",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Технологія захисного скла": "Corning Gorilla Glass Victus 2",
|
7 |
+
"Стандарти зв'язку": "2G, 3G, 4G, 5G",
|
8 |
+
"Кількість SIM-карт": "2 SIM",
|
9 |
+
"Розмір SIM-карти": "Nano-SIM",
|
10 |
+
"Підтримка e-SIM": "Є",
|
11 |
+
"Операційна система": "Android 13",
|
12 |
+
"Модель процесора": "Qualcomm Snapdragon 8 Gen 2",
|
13 |
+
"Кількість ядер": "8 ядер",
|
14 |
+
"Модель графічного процесора": "Qualcomm Adreno 740",
|
15 |
+
"Оперативна пам'ять": "8 ГБ",
|
16 |
+
"Вбудована пам'ять": "256 ГБ",
|
17 |
+
"Основна камера": "50+10+12 Мп",
|
18 |
+
"Роздільна здатність відео": "7680 x 4320 8K UHD",
|
19 |
+
"Фронтальна камера": "12 Мп",
|
20 |
+
"Спалах": "Так",
|
21 |
+
"Стабілізація": "Оптична",
|
22 |
+
"Зум": "3х оптичний\n30х цифровий",
|
23 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
24 |
+
"Bluetooth": "Версія 5.3",
|
25 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
26 |
+
"NFC": "Так",
|
27 |
+
"Інтерфейс USB": "USB Type-C",
|
28 |
+
"Ємність акумулятора": "3900 мАг",
|
29 |
+
"Бездротова зарядка": "Є",
|
30 |
+
"Потужність зарядки": "25 Вт",
|
31 |
+
"Час роботи в режимі розмови": "До 35 г",
|
32 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
33 |
+
"Клас захисту": "IP68",
|
34 |
+
"Біометричний захист": "Сканер відбитків пальців",
|
35 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
36 |
+
"Матеріал корпусу": "Метал\nПластик\nСкло",
|
37 |
+
"Висота": "146,3 мм",
|
38 |
+
"Ширина": "70,9 мм",
|
39 |
+
"Глибина": "7,6 мм",
|
40 |
+
"Вага": "168 г",
|
41 |
+
"Колір виробника": "Чорний",
|
42 |
+
"Гарантійний термін": "1 рік",
|
43 |
+
"Країна виробництва": "В'єтнам",
|
44 |
+
"Бренд": "Samsung",
|
45 |
+
"name": "Samsung Galaxy S23 8/256Gb Black (SM-S911BZKGSEK)",
|
46 |
+
"Ціна": "28 999 ₴"
|
47 |
+
}
|
prod_spec/7d97ed27b36a42f0cda0713ff8f2004b.json
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,1''",
|
3 |
+
"Роздільна здатність екрану": "2532х1170",
|
4 |
+
"Тип екрану": "Super Retina XDR",
|
5 |
+
"Технологія захисного скла": "Ceramic Shield",
|
6 |
+
"Стандарти зв'язку": "2G, 3G, 4G, 5G",
|
7 |
+
"Кількість SIM-карт": "1 SIM",
|
8 |
+
"Розмір SIM-карти": "Nano-SIM",
|
9 |
+
"Підтримка e-SIM": "Є",
|
10 |
+
"Операційна система": "Apple iOS 15",
|
11 |
+
"Модель процесора": "Apple A15 Bionic",
|
12 |
+
"Кількість ядер": "6 ядер",
|
13 |
+
"Вбудована пам'ять": "128 ГБ",
|
14 |
+
"Основна камера": "12+12 Мп",
|
15 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
16 |
+
"Фронтальна камера": "12 Мп",
|
17 |
+
"Спалах": "True Tone",
|
18 |
+
"Стабілізація": "Оптична",
|
19 |
+
"Зум": "2х оптичний\n5х цифровий",
|
20 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
21 |
+
"Bluetooth": "Версія 5.0",
|
22 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
23 |
+
"NFC": "Так",
|
24 |
+
"Інтерфейс USB": "Lightning",
|
25 |
+
"Ємність акумулятора": "3265 мАг",
|
26 |
+
"Швидка зарядка": "Є",
|
27 |
+
"Бездротова зарядка": "Є",
|
28 |
+
"Потужність зарядки": "20 Вт",
|
29 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
30 |
+
"Клас захисту": "IP68",
|
31 |
+
"Біометричний захист": "Розпізнавання обличчя",
|
32 |
+
"Комплектація": "Смартфон\nКабель Lightning\nІнструкція\nГарантійний талон",
|
33 |
+
"Матеріал корпусу": "Метал\nСкло",
|
34 |
+
"Висота": "146,7 мм",
|
35 |
+
"Ширина": "71,5 мм",
|
36 |
+
"Глибина": "7,65 мм",
|
37 |
+
"Вага": "174 г",
|
38 |
+
"Габарити упаковки (ВхШхГ)": "8х2х18 см",
|
39 |
+
"Вага в упаковці, кг": "0,332 кг",
|
40 |
+
"Колір виробника": "Синій",
|
41 |
+
"Гарантійний термін": "1 рік",
|
42 |
+
"Країна виробництва": "Китай",
|
43 |
+
"Бренд": "Apple",
|
44 |
+
"name": "Apple iPhone 13 128Gb Blue",
|
45 |
+
"Ціна": "26 999 ₴"
|
46 |
+
}
|
prod_spec/a39dfd476d7def865467f2ff33b23058.json
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,5''",
|
3 |
+
"Роздільна здатність екрану": "2340x1080",
|
4 |
+
"Тип екрану": "Super Amoled",
|
5 |
+
"Частота оновлення екрану": "90 Гц",
|
6 |
+
"Стандарти зв'язку": "3G, 4G",
|
7 |
+
"Кількість SIM-карт": "SIM + SIM/microSD",
|
8 |
+
"Розмір SIM-карти": "Nano-SIM",
|
9 |
+
"Операційна система": "Android 14",
|
10 |
+
"Модель процесора": "MediaTek Helio G99",
|
11 |
+
"Кількість ядер": "8 ядер",
|
12 |
+
"Частота процессора": "2 x 2,2 ГГц + 6 x 2,0 ГГц",
|
13 |
+
"Модель графічного процесора": "ARM Mali-G57 MC2",
|
14 |
+
"Оперативна пам'ять": "4 ГБ",
|
15 |
+
"Вбудована пам'ять": "128 ГБ",
|
16 |
+
"Розширення пам'яті": "microSD 1 ТБ",
|
17 |
+
"Основна камера": "50+5+2 Мп",
|
18 |
+
"Роздільна здатність відео": "1920 x 1080 Full HD",
|
19 |
+
"Фронтальна камера": "13 Мп",
|
20 |
+
"Спалах": "Так",
|
21 |
+
"Зум": "10х цифровий",
|
22 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
23 |
+
"Bluetooth": "Версія 5.3",
|
24 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
25 |
+
"NFC": "Так",
|
26 |
+
"Інтерфейс USB": "USB Type-C",
|
27 |
+
"Роз'єм 3,5 мм": "Так",
|
28 |
+
"Ємність акумулятора": "5000 мАг",
|
29 |
+
"Швидка зарядка": "Є",
|
30 |
+
"Потужність зарядки": "15 Вт",
|
31 |
+
"Час роботи в режимі розмови": "До 51 г",
|
32 |
+
"Біометричний захист": "Сканер відбитків пальців",
|
33 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
34 |
+
"Матеріал корпусу": "Пластик\nСкло",
|
35 |
+
"Висота": "160,1 мм",
|
36 |
+
"Ширина": "76,8 мм",
|
37 |
+
"Глибина": "8,4 мм",
|
38 |
+
"Вага": "200 г",
|
39 |
+
"Колір виробника": "Чорний",
|
40 |
+
"Гарантійний термін": "1 рік",
|
41 |
+
"Країна виробництва": "В'єтнам",
|
42 |
+
"Бренд": "Samsung",
|
43 |
+
"name": "Samsung Galaxy A15 4/128Gb Black (SM-A155FZKDEUC)",
|
44 |
+
"Ціна": "6 599 ₴"
|
45 |
+
}
|
prod_spec/ada36c2b1b7ea990b1f063c4bf219b6e.json
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,7\"",
|
3 |
+
"Роздільна здатність екрану": "3120x1440",
|
4 |
+
"Тип екрану": "Dynamic Amoled 2x",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Стандарти зв'язку": "3G, 4G, 5G",
|
7 |
+
"Кількість SIM-карт": "2 SIM",
|
8 |
+
"Розмір SIM-карти": "Nano-SIM",
|
9 |
+
"Підтримка e-SIM": "Є",
|
10 |
+
"Операційна система": "Android 14",
|
11 |
+
"Модель процесора": "Exynos 2400",
|
12 |
+
"Кількість ядер": "10 ядер",
|
13 |
+
"Оперативна пам'ять": "12 ГБ",
|
14 |
+
"Вбудована пам'ять": "512 ГБ",
|
15 |
+
"Основна камера": "50+10+12 Мп",
|
16 |
+
"Роздільна здатність відео": "7680 x 4320 8K UHD",
|
17 |
+
"Фронтальна камера": "12 Мп",
|
18 |
+
"Спалах": "Так",
|
19 |
+
"Стабілізація": "Оптична",
|
20 |
+
"Зум": "2х оптичний\n3х оптичний\n30х цифровий",
|
21 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
22 |
+
"Bluetooth": "Версія 5.3",
|
23 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS",
|
24 |
+
"NFC": "Так",
|
25 |
+
"Інтерфейс USB": "USB Type-C",
|
26 |
+
"Ємність акумулятора": "4900 мАг",
|
27 |
+
"Швидка зарядка": "Є",
|
28 |
+
"Бездротова зарядка": "Є",
|
29 |
+
"Потужність зарядки": "45 Вт",
|
30 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
31 |
+
"Клас захисту": "IP68",
|
32 |
+
"Біометричний захист": "Сканер відбитків пальців під екраном",
|
33 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
34 |
+
"Матеріал корпусу": "Метал",
|
35 |
+
"Висота": "158,5 мм",
|
36 |
+
"Ширина": "75,6 мм",
|
37 |
+
"Глибина": "7,7 мм",
|
38 |
+
"Вага": "197 г",
|
39 |
+
"Колір виробника": "Чорний",
|
40 |
+
"Гарантійний термін": "1 рік",
|
41 |
+
"Країна виробництва": "В'єтнам",
|
42 |
+
"Бренд": "Samsung",
|
43 |
+
"name": "Samsung Galaxy S24+ 12/512Gb Onyx Black (SM-S926BZKGEUC)",
|
44 |
+
"Ціна": "45 899 ₴"
|
45 |
+
}
|
prod_spec/b0c5c0cc417d3aebdb7be808aae45864.json
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,1''",
|
3 |
+
"Роздільна здатність екрану": "2532х1170",
|
4 |
+
"Тип екрану": "Super Retina XDR",
|
5 |
+
"Технологія захисного скла": "Ceramic Shield",
|
6 |
+
"Стандарти зв'язку": "2G, 3G, 4G, 5G",
|
7 |
+
"Кількість SIM-карт": "1 SIM",
|
8 |
+
"Розмір SIM-карти": "Nano-SIM",
|
9 |
+
"Підтримка e-SIM": "Є",
|
10 |
+
"Операційна система": "Apple iOS 15",
|
11 |
+
"Модель процесора": "Apple A15 Bionic",
|
12 |
+
"Кількість ядер": "6 ядер",
|
13 |
+
"Вбудована пам'ять": "128 ГБ",
|
14 |
+
"Основна камера": "12+12 Мп",
|
15 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
16 |
+
"Фронтальна камера": "12 Мп",
|
17 |
+
"Спалах": "True Tone",
|
18 |
+
"Стабілізація": "Оптична",
|
19 |
+
"Зум": "2х оптичний\n5х цифровий",
|
20 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
21 |
+
"Bluetooth": "Версія 5.0",
|
22 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
23 |
+
"NFC": "Так",
|
24 |
+
"Інтерфейс USB": "Lightning",
|
25 |
+
"Ємність акумулятора": "3265 мАг",
|
26 |
+
"Швидка зарядка": "Є",
|
27 |
+
"Бездротова зарядка": "Є",
|
28 |
+
"Потужність зарядки": "20 Вт",
|
29 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
30 |
+
"Клас захисту": "IP68",
|
31 |
+
"Біометричний захист": "Розпізнавання обличчя",
|
32 |
+
"Комплектація": "Смартфон\nКабель Lightning\nІнструкція\nГарантійний талон",
|
33 |
+
"Матеріал корпусу": "Метал\nСкло",
|
34 |
+
"Висота": "146,7 мм",
|
35 |
+
"Ширина": "71,5 мм",
|
36 |
+
"Глибина": "7,65 мм",
|
37 |
+
"Вага": "174 г",
|
38 |
+
"Габарити упаковки (ВхШхГ)": "8х2х18 см",
|
39 |
+
"Вага в упаковці, кг": "0,332 кг",
|
40 |
+
"Колір виробника": "Рожевий",
|
41 |
+
"Гарантійний термін": "1 рік",
|
42 |
+
"Країна виробництва": "Китай",
|
43 |
+
"Бренд": "Apple",
|
44 |
+
"name": "Apple iPhone 13 128Gb Pink",
|
45 |
+
"Ціна": "26 999 ₴"
|
46 |
+
}
|
prod_spec/bc7488865087cd682d6dbfcaa527513f.json
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,1''",
|
3 |
+
"Роздільна здатність екрану": "2556х1179",
|
4 |
+
"Тип екрану": "Super Retina XDR",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Технологія захисного скла": "Ceramic Shield",
|
7 |
+
"Стандарти зв'язку": "3G, 4G, 5G",
|
8 |
+
"Кількість SIM-карт": "1 SIM + e-SIM",
|
9 |
+
"Розмір SIM-карти": "Nano-SIM",
|
10 |
+
"Підтримка e-SIM": "Є",
|
11 |
+
"Операційна система": "Apple iOS 17",
|
12 |
+
"Модель процесора": "Apple A17 Pro Bionic",
|
13 |
+
"Кількість ядер": "6 ядер",
|
14 |
+
"Вбудована пам'ять": "128 ГБ",
|
15 |
+
"Основна камера": "48+12+12 Мп",
|
16 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
17 |
+
"Фронтальна камера": "12 Мп",
|
18 |
+
"Спалах": "True Tone",
|
19 |
+
"Стабілізація": "Матрична/оптична",
|
20 |
+
"Зум": "3х оптичний\n15х цифровий",
|
21 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
22 |
+
"Bluetooth": "Версія 5.3",
|
23 |
+
"Навігаційна система": "GPS\nA-GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
24 |
+
"NFC": "Так",
|
25 |
+
"Інтерфейс USB": "USB Type-C",
|
26 |
+
"Швидка зарядка": "Є",
|
27 |
+
"Бездротова зарядка": "Є",
|
28 |
+
"Потужність зарядки": "20 Вт",
|
29 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
30 |
+
"Клас захисту": "IP68",
|
31 |
+
"Біометричний захист": "Розпізнавання обличчя",
|
32 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
33 |
+
"Матеріал корпусу": "Скло\nТитан",
|
34 |
+
"Висота": "146,6 мм",
|
35 |
+
"Ширина": "70,6 мм",
|
36 |
+
"Глибина": "8,25 мм",
|
37 |
+
"Вага": "187 г",
|
38 |
+
"Колір виробника": "Синій",
|
39 |
+
"Гарантійний термін": "1 рік",
|
40 |
+
"Країна виробництва": "Китай",
|
41 |
+
"Бренд": "Apple",
|
42 |
+
"name": "Apple iPhone 15 Pro 128Gb Blue Titanium",
|
43 |
+
"Ціна": "45 999 ₴"
|
44 |
+
}
|
prod_spec/ce304e71a27074ee7e94843b2768b741.json
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,8\"",
|
3 |
+
"Роздільна здатність екрану": "3120x1440",
|
4 |
+
"Тип екрану": "Dynamic Amoled 2x",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Стандарти зв'язку": "3G, 4G, 5G",
|
7 |
+
"Кількість SIM-карт": "2 SIM",
|
8 |
+
"Розмір SIM-карти": "Nano-SIM",
|
9 |
+
"Підтримка e-SIM": "Є",
|
10 |
+
"Операційна система": "Android 14",
|
11 |
+
"Модель процесора": "Qualcomm Snapdragon 8 Gen 3",
|
12 |
+
"Кількість ядер": "8 ядер",
|
13 |
+
"Оперативна пам'ять": "12 ГБ",
|
14 |
+
"Вбудована пам'ять": "256 ГБ",
|
15 |
+
"Основна камера": "200+50+10+12 Мп",
|
16 |
+
"Роздільна здатність відео": "7680 x 4320 8K UHD",
|
17 |
+
"Фронтальна камера": "12 Мп",
|
18 |
+
"Спалах": "Так",
|
19 |
+
"Стабілізація": "Оптична",
|
20 |
+
"Зум": "3х оптичний\n5х оптичний\n100х цифровий",
|
21 |
+
"Стандарти Wi-Fi": "802.11be (Wi-Fi 7)",
|
22 |
+
"Bluetooth": "Версія 5.3",
|
23 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS",
|
24 |
+
"NFC": "Так",
|
25 |
+
"Інтерфейс USB": "USB Type-C",
|
26 |
+
"Ємність акумулятора": "5000 мАг",
|
27 |
+
"Швидка зарядка": "Є",
|
28 |
+
"Бездротова зарядка": "Є",
|
29 |
+
"Потужність зарядки": "45 Вт",
|
30 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
31 |
+
"Клас захисту": "IP68",
|
32 |
+
"Біометричний захист": "Сканер відбитків пальців під екраном",
|
33 |
+
"Комплектація": "Смартфон\nКабель Type-C\nСтілус\nІнструкція\nГарантійний талон",
|
34 |
+
"Матеріал корпусу": "Титан",
|
35 |
+
"Висота": "162,3 мм",
|
36 |
+
"Ширина": "79 мм",
|
37 |
+
"Глибина": "8,6 мм",
|
38 |
+
"Вага": "233 г",
|
39 |
+
"Колір виробника": "Сірий",
|
40 |
+
"Гарантійний термін": "1 рік",
|
41 |
+
"Країна виробництва": "В'єтнам",
|
42 |
+
"Бренд": "Samsung",
|
43 |
+
"name": "Samsung Galaxy S24 Ultra 12/256Gb Titanium Gray (SM-S928BZTGEUC)",
|
44 |
+
"Ціна": "52 999 ₴"
|
45 |
+
}
|
prod_spec/ce6cad45e78427fedabdd8d0a8616e87.json
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,1''",
|
3 |
+
"Роздільна здатність екрану": "2556х1179",
|
4 |
+
"Тип екрану": "Super Retina XDR",
|
5 |
+
"Технологія захисного скла": "Ceramic Shield",
|
6 |
+
"Стандарти зв'язку": "3G, 4G, 5G",
|
7 |
+
"Кількість SIM-карт": "1 SIM + e-SIM",
|
8 |
+
"Розмір SIM-карти": "Nano-SIM",
|
9 |
+
"Підтримка e-SIM": "Є",
|
10 |
+
"Операційна система": "Apple iOS 17",
|
11 |
+
"Модель процесора": "Apple A16 Bionic",
|
12 |
+
"Кількість ядер": "6 ядер",
|
13 |
+
"Вбудована пам'ять": "128 ГБ",
|
14 |
+
"Основна камера": "48+12+12 Мп",
|
15 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
16 |
+
"Фронтальна камера": "12 Мп",
|
17 |
+
"Спалах": "True Tone",
|
18 |
+
"Стабілізація": "Матрична/оптична",
|
19 |
+
"Зум": "2х оптичний\n10х цифровий",
|
20 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
21 |
+
"Bluetooth": "Версія 5.3",
|
22 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
23 |
+
"NFC": "Так",
|
24 |
+
"Інтерфейс USB": "USB Type-C",
|
25 |
+
"Швидка зарядка": "Є",
|
26 |
+
"Бездротова зарядка": "Є",
|
27 |
+
"Потужність зарядки": "20 Вт",
|
28 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
29 |
+
"Клас захисту": "IP68",
|
30 |
+
"Біометричний захист": "Розпізнавання обличчя",
|
31 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
32 |
+
"Матеріал корпусу": "Метал\nСкло",
|
33 |
+
"Висота": "147,6 мм",
|
34 |
+
"Ширина": "71,6 мм",
|
35 |
+
"Глибина": "7,8 мм",
|
36 |
+
"Вага": "171 г",
|
37 |
+
"Колір виробника": "Чорний",
|
38 |
+
"Гарантійний термін": "1 рік",
|
39 |
+
"Країна виробництва": "Китай",
|
40 |
+
"Бренд": "Apple",
|
41 |
+
"name": "Apple iPhone 15 128Gb Black",
|
42 |
+
"Ціна": "39 499 ₴"
|
43 |
+
}
|
prod_spec/d5af58d68526a8bd7ecd15d583aab727.json
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,2''",
|
3 |
+
"Роздільна здатність екрану": "2340x1080",
|
4 |
+
"Тип екрану": "Dynamic Amoled 2x",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Стандарти зв'язку": "3G, 4G, 5G",
|
7 |
+
"Кількість SIM-карт": "2 SIM",
|
8 |
+
"Розмір SIM-карти": "Nano-SIM",
|
9 |
+
"Підтримка e-SIM": "Є",
|
10 |
+
"Операційна система": "Android 14",
|
11 |
+
"Модель процесора": "Exynos 2400",
|
12 |
+
"Кількість ядер": "10 ядер",
|
13 |
+
"Оперативна пам'ять": "8 ГБ",
|
14 |
+
"Вбудована пам'ять": "256 ГБ",
|
15 |
+
"Основна камера": "50+10+12 Мп",
|
16 |
+
"Роздільна здатність відео": "7680 x 4320 8K UHD",
|
17 |
+
"Фронтальна камера": "12 Мп",
|
18 |
+
"Спалах": "Так",
|
19 |
+
"Стабілізація": "Оптична",
|
20 |
+
"Зум": "2х оптичний\n3х оптичний\n30х цифровий",
|
21 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
22 |
+
"Bluetooth": "Версія 5.3",
|
23 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS",
|
24 |
+
"NFC": "Так",
|
25 |
+
"Інтерфейс USB": "USB Type-C",
|
26 |
+
"Ємність акумулятора": "4000 мАг",
|
27 |
+
"Швидка зарядка": "Є",
|
28 |
+
"Бездротова зарядка": "Є",
|
29 |
+
"Потужність зарядки": "25 Вт",
|
30 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
31 |
+
"Клас захисту": "IP68",
|
32 |
+
"Біометричний захист": "Сканер відбитків пальців під екраном",
|
33 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
34 |
+
"Матеріал корпусу": "Метал",
|
35 |
+
"Висота": "147 мм",
|
36 |
+
"Ширина": "70,6 мм",
|
37 |
+
"Глибина": "7,6 мм",
|
38 |
+
"Вага": "167 г",
|
39 |
+
"Колір виробника": "Чорний",
|
40 |
+
"Гарантійний термін": "1 рік",
|
41 |
+
"Країна виробництва": "В'єтнам",
|
42 |
+
"Бренд": "Samsung",
|
43 |
+
"name": "Samsung Galaxy S24 8/256Gb Onyx Black (SM-S921BZKGEUC)",
|
44 |
+
"Ціна": "35 999 ₴"
|
45 |
+
}
|
prod_spec/dd0b92f289d389082747fd1c667feaec.json
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,1''",
|
3 |
+
"Роздільна здатність екрану": "2532х1170",
|
4 |
+
"Тип екрану": "Super Retina XDR",
|
5 |
+
"Технологія захисного скла": "Ceramic Shield",
|
6 |
+
"Стандарти зв'язку": "2G, 3G, 4G, 5G",
|
7 |
+
"Кількість SIM-карт": "1 SIM",
|
8 |
+
"Розмір SIM-карти": "Nano-SIM",
|
9 |
+
"Підтримка e-SIM": "Є",
|
10 |
+
"Операційна система": "Apple iOS 15",
|
11 |
+
"Модель процесора": "Apple A15 Bionic",
|
12 |
+
"Кількість ядер": "6 ядер",
|
13 |
+
"Вбудована пам'ять": "128 ГБ",
|
14 |
+
"Основна камера": "12+12 Мп",
|
15 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
16 |
+
"Фронтальна камера": "12 Мп",
|
17 |
+
"Спалах": "True Tone",
|
18 |
+
"Стабілізація": "Оптична",
|
19 |
+
"Зум": "2х оптичний\n5х цифровий",
|
20 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
21 |
+
"Bluetooth": "Версія 5.0",
|
22 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
23 |
+
"NFC": "Так",
|
24 |
+
"Інтерфейс USB": "Lightning",
|
25 |
+
"Ємність акумулятора": "3265 мАг",
|
26 |
+
"Швидка зарядка": "Є",
|
27 |
+
"Бездротова зарядка": "Є",
|
28 |
+
"Потужність зарядки": "20 Вт",
|
29 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
30 |
+
"Клас захисту": "IP68",
|
31 |
+
"Біометричний захист": "Розпізнавання обличчя",
|
32 |
+
"Комплектація": "Смартфон\nКабель Lightning\nІнструкція\nГарантійний талон",
|
33 |
+
"Матеріал корпусу": "Метал\nСкло",
|
34 |
+
"Висота": "146,7 мм",
|
35 |
+
"Ширина": "71,5 мм",
|
36 |
+
"Глибина": "7,65 мм",
|
37 |
+
"Вага": "174 г",
|
38 |
+
"Габарити упаковки (ВхШхГ)": "8х2х18 см",
|
39 |
+
"Вага в упаковці, кг": "0,332 кг",
|
40 |
+
"Колір виробника": "Білий",
|
41 |
+
"Гарантійний термін": "1 рік",
|
42 |
+
"Країна виробництва": "Китай",
|
43 |
+
"Бренд": "Apple",
|
44 |
+
"name": "Apple iPhone 13 128Gb Starlight",
|
45 |
+
"Ціна": "26 999 ₴"
|
46 |
+
}
|
prod_spec/e373d4ddf0592f3f577622c288512bfb.json
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,6\"",
|
3 |
+
"Роздільна здатність екрану": "2340x1080",
|
4 |
+
"Тип екрану": "Super Amoled",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Технологія захисного скла": "Corning Gorilla Glass Victus+",
|
7 |
+
"Стандарти зв'язку": "2G GSM, 3G WCDMA, 4G LTE FDD, 4G LTE TDD, 5G Sub6 FDD, 5G Sub6 TDD",
|
8 |
+
"Кількість SIM-карт": "SIM + SIM/microSD",
|
9 |
+
"Розмір SIM-карти": "Nano-SIM",
|
10 |
+
"Підтримка e-SIM": "Є",
|
11 |
+
"Модель процесора": "Exynos 1380",
|
12 |
+
"Кількість ядер": "8 ядер",
|
13 |
+
"Частота процессора": "4 х 2,4 ГГц + 4 х 2,0 ГГц",
|
14 |
+
"Модель графічного процесора": "ARM Mali-G68 MP5",
|
15 |
+
"Оперативна пам'ять": "6 ГБ",
|
16 |
+
"Вбудована пам'ять": "128 ГБ",
|
17 |
+
"Розширення пам'яті": "microSD 1 ТБ",
|
18 |
+
"Основна камера": "50+8+5 Мп",
|
19 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
20 |
+
"Фронтальна камера": "13 Мп",
|
21 |
+
"Спалах": "Так",
|
22 |
+
"Зум": "10х цифровий",
|
23 |
+
"Стандарти Wi-Fi": "802.11ax (Wi-Fi 6)",
|
24 |
+
"Bluetooth": "Версія 5.3",
|
25 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS",
|
26 |
+
"NFC": "Так",
|
27 |
+
"Інтерфейс USB": "USB Type-C",
|
28 |
+
"Ємність акумулятора": "5000 мАг",
|
29 |
+
"Швидка зарядка": "Є",
|
30 |
+
"Потужність зарядки": "25 Вт",
|
31 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
32 |
+
"Клас захисту": "IP67",
|
33 |
+
"Біометричний захист": "Сканер відбитків пальців",
|
34 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
35 |
+
"Матеріал корпусу": "Пластик\nСкло",
|
36 |
+
"Висота": "161,7 мм",
|
37 |
+
"Ширина": "78 мм",
|
38 |
+
"Глибина": "8,2 мм",
|
39 |
+
"Вага": "209 г",
|
40 |
+
"Колір виробника": "Синій",
|
41 |
+
"Гарантійний термін": "1 рік",
|
42 |
+
"Країна виробництва": "В'єтнам",
|
43 |
+
"Бренд": "Samsung",
|
44 |
+
"name": "Samsung Galaxy A35 5G 6/128Gb Awesome Navy (SM-A356BZKBEUC)",
|
45 |
+
"Ціна": "13 499 ₴"
|
46 |
+
}
|
prod_spec/e97ecbb4438393500c2773eb4066c607.json
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,1''",
|
3 |
+
"Роздільна здатність екрану": "2556х1179",
|
4 |
+
"Тип екрану": "Super Retina XDR",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Технологія захисного скла": "Ceramic Shield",
|
7 |
+
"Стандарти зв'язку": "3G, 4G, 5G",
|
8 |
+
"Кількість SIM-карт": "1 SIM + e-SIM",
|
9 |
+
"Розмір SIM-карти": "Nano-SIM",
|
10 |
+
"Підтримка e-SIM": "Є",
|
11 |
+
"Операційна система": "Apple iOS 17",
|
12 |
+
"Модель процесора": "Apple A17 Pro Bionic",
|
13 |
+
"Кількість ядер": "6 ядер",
|
14 |
+
"Вбудована пам'ять": "128 ГБ",
|
15 |
+
"Основна камера": "48+12+12 Мп",
|
16 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
17 |
+
"Фронтальна камера": "12 Мп",
|
18 |
+
"Спалах": "True Tone",
|
19 |
+
"Стабілізація": "Матрична/оптична",
|
20 |
+
"Зум": "3х оптичний\n15х цифровий",
|
21 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
22 |
+
"Bluetooth": "Версія 5.3",
|
23 |
+
"Навігаційна система": "GPS\nA-GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
24 |
+
"NFC": "Так",
|
25 |
+
"Інтерфейс USB": "USB Type-C",
|
26 |
+
"Швидка зарядка": "Є",
|
27 |
+
"Бездротова зарядка": "Є",
|
28 |
+
"Потужність зарядки": "20 Вт",
|
29 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
30 |
+
"Клас захисту": "IP68",
|
31 |
+
"Біометричний захист": "Розпізнавання обличчя",
|
32 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
33 |
+
"Матеріал корпусу": "Скло\nТитан",
|
34 |
+
"Висота": "146,6 мм",
|
35 |
+
"Ширина": "70,6 мм",
|
36 |
+
"Глибина": "8,25 мм",
|
37 |
+
"Вага": "187 г",
|
38 |
+
"Колір виробника": "Сріблястий",
|
39 |
+
"Гарантійний термін": "1 рік",
|
40 |
+
"Країна виробництва": "Китай",
|
41 |
+
"Бренд": "Apple",
|
42 |
+
"name": "Apple iPhone 15 Pro 128Gb Natural Titanium",
|
43 |
+
"Ціна": "45 999 ₴"
|
44 |
+
}
|
prod_spec/f179142d7ad089f7d714b042fe0e4c5a.json
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,5''",
|
3 |
+
"Роздільна здатність екрану": "2340x1080",
|
4 |
+
"Тип екрану": "Super Amoled",
|
5 |
+
"Частота оновлення екрану": "120 Гц",
|
6 |
+
"Стандарти зв'язку": "3G, 4G, 5G",
|
7 |
+
"Кількість SIM-карт": "SIM + SIM/microSD",
|
8 |
+
"Розмір SIM-карти": "Nano-SIM",
|
9 |
+
"Операційна система": "Android 14",
|
10 |
+
"Модель процесора": "Exynos 1280",
|
11 |
+
"Кількість ядер": "8 ядер",
|
12 |
+
"Частота процессора": "2 х 2,4 ГГц + 6 х 2 ГГц",
|
13 |
+
"Модель графічного процесора": "ARM Mali-G68",
|
14 |
+
"Оперативна пам'ять": "6 ГБ",
|
15 |
+
"Вбудована пам'ять": "128 ГБ",
|
16 |
+
"Розширення пам'яті": "microSD 1 ТБ",
|
17 |
+
"Основна камера": "50+8+2 Мп",
|
18 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
19 |
+
"Фронтальна камера": "13 Мп",
|
20 |
+
"Спалах": "Так",
|
21 |
+
"Стабілізація": "Оптична",
|
22 |
+
"Зум": "10х цифровий",
|
23 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
24 |
+
"Bluetooth": "Версія 5.3",
|
25 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
26 |
+
"NFC": "Так",
|
27 |
+
"Інтерфейс USB": "USB Type-C",
|
28 |
+
"Роз'єм 3,5 мм": "Так",
|
29 |
+
"Ємність акумулятора": "5000 мАг",
|
30 |
+
"Швидка зарядка": "Є",
|
31 |
+
"Час роботи в режимі розмови": "До 38 г",
|
32 |
+
"Біометричний захист": "Сканер відбитків пальців",
|
33 |
+
"Комплектація": "Смартфон\nКабель Type-C\nІнструкція\nГарантійний талон",
|
34 |
+
"Матеріал корпусу": "Пластик",
|
35 |
+
"Висота": "161 мм",
|
36 |
+
"Ширина": "76,5 мм",
|
37 |
+
"Глибина": "8,3 мм",
|
38 |
+
"Колір виробника": "Чорний",
|
39 |
+
"Гарантійний термін": "1 рік",
|
40 |
+
"Країна виробництва": "В'єтнам",
|
41 |
+
"Бренд": "Samsung",
|
42 |
+
"name": "Samsung Galaxy A25 5G 6/128Gb Black (SM-A256BZKDEUC)",
|
43 |
+
"Ціна": "10 199 ₴"
|
44 |
+
}
|
prod_spec/fa82fa4dd848c6735dff3eb8b4480db7.json
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Діагональ дисплея": "6,1''",
|
3 |
+
"Роздільна здатність екрану": "2532х1170",
|
4 |
+
"Тип екрану": "Super Retina XDR",
|
5 |
+
"Технологія захисного скла": "Ceramic Shield",
|
6 |
+
"Стандарти зв'язку": "2G, 3G, 4G, 5G",
|
7 |
+
"Кількість SIM-карт": "1 SIM",
|
8 |
+
"Розмір SIM-карти": "Nano-SIM",
|
9 |
+
"Підтримка e-SIM": "Є",
|
10 |
+
"Операційна система": "Apple iOS 15",
|
11 |
+
"Модель процесора": "Apple A15 Bionic",
|
12 |
+
"Кількість ядер": "6 ядер",
|
13 |
+
"Вбудована пам'ять": "128 ГБ",
|
14 |
+
"Основна камера": "12+12 Мп",
|
15 |
+
"Роздільна здатність відео": "3840 x 2160 4K UHD",
|
16 |
+
"Фронтальна камера": "12 Мп",
|
17 |
+
"Спалах": "True Tone",
|
18 |
+
"Стабілізація": "Оптична",
|
19 |
+
"Зум": "2х оптичний\n5х цифровий",
|
20 |
+
"Стандарти Wi-Fi": "802.11aс (Wi-Fi 5)",
|
21 |
+
"Bluetooth": "Версія 5.0",
|
22 |
+
"Навігаційна система": "GPS\nBeidou\nGalileo\nQZSS\nГЛОНАСС",
|
23 |
+
"NFC": "Так",
|
24 |
+
"Інтерфейс USB": "Lightning",
|
25 |
+
"Ємність акумулятора": "3265 мАг",
|
26 |
+
"Швидка зарядка": "Є",
|
27 |
+
"Бездротова зарядка": "Є",
|
28 |
+
"Потужність зарядки": "20 Вт",
|
29 |
+
"Захист корпусу": "Захист від пилу та вологи",
|
30 |
+
"Клас захисту": "IP68",
|
31 |
+
"Біометричний захист": "Розпізнавання обличчя",
|
32 |
+
"Комплектація": "Смартфон\nКабель Lightning\nІнструкція\nГарантійний талон",
|
33 |
+
"Матеріал корпусу": "Метал\nСкло",
|
34 |
+
"Висота": "146,7 мм",
|
35 |
+
"Ширина": "71,5 мм",
|
36 |
+
"Глибина": "7,65 мм",
|
37 |
+
"Вага": "174 г",
|
38 |
+
"Габарити упаковки (ВхШхГ)": "8х2х18 см",
|
39 |
+
"Вага в упаковці, кг": "0,332 кг",
|
40 |
+
"Колір виробника": "Чорний",
|
41 |
+
"Гарантійний термін": "1 рік",
|
42 |
+
"Країна виробництва": "Китай",
|
43 |
+
"Бренд": "Apple",
|
44 |
+
"name": "Apple iPhone 13 128Gb Midnight",
|
45 |
+
"Ціна": "26 999 ₴"
|
46 |
+
}
|
requirements.txt
ADDED
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
aiofiles==23.2.1
|
2 |
+
aiohappyeyeballs==2.3.4
|
3 |
+
aiohttp==3.10.1
|
4 |
+
aiosignal==1.3.1
|
5 |
+
altair==5.3.0
|
6 |
+
annotated-types==0.7.0
|
7 |
+
anyio==4.4.0
|
8 |
+
appnope==0.1.4
|
9 |
+
asttokens==2.4.1
|
10 |
+
attrs==24.1.0
|
11 |
+
beautifulsoup4==4.12.3
|
12 |
+
blinker==1.8.2
|
13 |
+
cachetools==5.4.0
|
14 |
+
certifi==2024.7.4
|
15 |
+
cffi==1.16.0
|
16 |
+
charset-normalizer==3.3.2
|
17 |
+
click==8.1.7
|
18 |
+
comm==0.2.2
|
19 |
+
contourpy==1.2.1
|
20 |
+
cycler==0.12.1
|
21 |
+
dataclasses-json==0.6.7
|
22 |
+
debugpy==1.8.5
|
23 |
+
decorator==5.1.1
|
24 |
+
Deprecated==1.2.14
|
25 |
+
dirtyjson==1.0.8
|
26 |
+
distro==1.9.0
|
27 |
+
executing==2.0.1
|
28 |
+
fastapi==0.112.0
|
29 |
+
ffmpy==0.4.0
|
30 |
+
filelock==3.15.4
|
31 |
+
fonttools==4.53.1
|
32 |
+
frozenlist==1.4.1
|
33 |
+
fsspec==2024.6.1
|
34 |
+
future==1.0.0
|
35 |
+
geocoder==1.38.1
|
36 |
+
gitdb==4.0.11
|
37 |
+
GitPython==3.1.43
|
38 |
+
gradio==4.41.0
|
39 |
+
gradio_client==1.3.0
|
40 |
+
greenlet==3.0.3
|
41 |
+
h11==0.14.0
|
42 |
+
h3==3.7.7
|
43 |
+
httpcore==1.0.5
|
44 |
+
httpx==0.27.0
|
45 |
+
huggingface-hub==0.24.5
|
46 |
+
idna==3.7
|
47 |
+
importlib_resources==6.4.0
|
48 |
+
ipykernel==6.29.5
|
49 |
+
ipython==8.26.0
|
50 |
+
jedi==0.19.1
|
51 |
+
Jinja2==3.1.4
|
52 |
+
joblib==1.4.2
|
53 |
+
jsonpickle==3.2.2
|
54 |
+
jsonschema==4.23.0
|
55 |
+
jsonschema-specifications==2023.12.1
|
56 |
+
jupyter_client==8.6.2
|
57 |
+
jupyter_core==5.7.2
|
58 |
+
kiwisolver==1.4.5
|
59 |
+
llama-cloud==0.0.11
|
60 |
+
llama-index==0.10.61
|
61 |
+
llama-index-agent-openai==0.2.9
|
62 |
+
llama-index-cli==0.1.13
|
63 |
+
llama-index-core==0.10.61
|
64 |
+
llama-index-embeddings-openai==0.1.11
|
65 |
+
llama-index-indices-managed-llama-cloud==0.2.7
|
66 |
+
llama-index-legacy==0.9.48
|
67 |
+
llama-index-llms-openai==0.1.27
|
68 |
+
llama-index-multi-modal-llms-openai==0.1.8
|
69 |
+
llama-index-program-openai==0.1.7
|
70 |
+
llama-index-question-gen-openai==0.1.3
|
71 |
+
llama-index-readers-file==0.1.32
|
72 |
+
llama-index-readers-llama-parse==0.1.6
|
73 |
+
llama-parse==0.4.9
|
74 |
+
markdown-it-py==3.0.0
|
75 |
+
MarkupSafe==2.1.5
|
76 |
+
marshmallow==3.21.3
|
77 |
+
matplotlib==3.9.1.post1
|
78 |
+
matplotlib-inline==0.1.7
|
79 |
+
mdurl==0.1.2
|
80 |
+
multidict==6.0.5
|
81 |
+
mypy-extensions==1.0.0
|
82 |
+
nest-asyncio==1.6.0
|
83 |
+
networkx==3.3
|
84 |
+
nltk==3.8.1
|
85 |
+
numpy==1.26.4
|
86 |
+
openai==1.39.0
|
87 |
+
orjson==3.10.7
|
88 |
+
packaging==24.1
|
89 |
+
pandas==2.2.2
|
90 |
+
parso==0.8.4
|
91 |
+
pexpect==4.9.0
|
92 |
+
pillow==10.4.0
|
93 |
+
platformdirs==4.2.2
|
94 |
+
playwright==1.45.1
|
95 |
+
prompt_toolkit==3.0.47
|
96 |
+
protobuf==5.27.3
|
97 |
+
psutil==6.0.0
|
98 |
+
ptyprocess==0.7.0
|
99 |
+
pure_eval==0.2.3
|
100 |
+
pyarrow==17.0.0
|
101 |
+
pycparser==2.22
|
102 |
+
pydantic==2.8.2
|
103 |
+
pydantic_core==2.20.1
|
104 |
+
pydeck==0.9.1
|
105 |
+
pydub==0.25.1
|
106 |
+
pyee==11.1.0
|
107 |
+
Pygments==2.18.0
|
108 |
+
pyparsing==3.1.2
|
109 |
+
pypdf==4.3.1
|
110 |
+
python-dateutil==2.9.0.post0
|
111 |
+
python-dotenv==1.0.1
|
112 |
+
python-multipart==0.0.9
|
113 |
+
pytz==2024.1
|
114 |
+
pyvis==0.3.2
|
115 |
+
PyYAML==6.0.1
|
116 |
+
pyzmq==26.1.0
|
117 |
+
ratelim==0.1.6
|
118 |
+
referencing==0.35.1
|
119 |
+
regex==2024.7.24
|
120 |
+
requests==2.32.3
|
121 |
+
rich==13.7.1
|
122 |
+
rpds-py==0.20.0
|
123 |
+
ruff==0.5.7
|
124 |
+
semantic-version==2.10.0
|
125 |
+
shellingham==1.5.4
|
126 |
+
six==1.16.0
|
127 |
+
smmap==5.0.1
|
128 |
+
sniffio==1.3.1
|
129 |
+
soupsieve==2.5
|
130 |
+
SQLAlchemy==2.0.32
|
131 |
+
stack-data==0.6.3
|
132 |
+
starlette==0.37.2
|
133 |
+
striprtf==0.0.26
|
134 |
+
tenacity==8.5.0
|
135 |
+
tiktoken==0.7.0
|
136 |
+
timezonefinder==6.5.2
|
137 |
+
toml==0.10.2
|
138 |
+
tomlkit==0.12.0
|
139 |
+
toolz==0.12.1
|
140 |
+
tornado==6.4.1
|
141 |
+
tqdm==4.66.5
|
142 |
+
traitlets==5.14.3
|
143 |
+
typer==0.12.3
|
144 |
+
typing-inspect==0.9.0
|
145 |
+
typing_extensions==4.12.2
|
146 |
+
tzdata==2024.1
|
147 |
+
urllib3==2.2.2
|
148 |
+
uvicorn==0.30.5
|
149 |
+
wcwidth==0.2.13
|
150 |
+
websockets==12.0
|
151 |
+
wrapt==1.16.0
|
152 |
+
yarl==1.9.4
|
retrieve.py
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from dotenv import load_dotenv
|
3 |
+
import json
|
4 |
+
from hashlib import md5
|
5 |
+
from typing import List
|
6 |
+
|
7 |
+
|
8 |
+
load_dotenv()
|
9 |
+
|
10 |
+
|
11 |
+
def get_product_spec(url: str) -> dict:
|
12 |
+
"""
|
13 |
+
Get the product specification from the cache.
|
14 |
+
|
15 |
+
Args:
|
16 |
+
url (str): The URL to get the product specification for.
|
17 |
+
|
18 |
+
Returns:
|
19 |
+
dict: The product specification from the cache.
|
20 |
+
"""
|
21 |
+
|
22 |
+
filename = md5(url.encode()).hexdigest()
|
23 |
+
filename = f"{filename}.json"
|
24 |
+
|
25 |
+
filepath = os.path.join(os.getenv("PROD_SPEC_DIR", "prod_spec"), filename)
|
26 |
+
try:
|
27 |
+
with open(filepath, "r") as f:
|
28 |
+
return json.load(f)
|
29 |
+
except Exception as e:
|
30 |
+
return False
|
31 |
+
|
32 |
+
def get_latest_dir(dir: str) -> str:
|
33 |
+
"""
|
34 |
+
Get the latest directory in the given directory.
|
35 |
+
|
36 |
+
Args:
|
37 |
+
dir (str): The parent directory to search for the latest directory.
|
38 |
+
|
39 |
+
Returns:
|
40 |
+
str: The path to the latest directory.
|
41 |
+
"""
|
42 |
+
|
43 |
+
dirs: List[str] = [
|
44 |
+
d for d in os.listdir(dir) if os.path.isdir(os.path.join(dir, d))
|
45 |
+
]
|
46 |
+
if not dirs:
|
47 |
+
raise ValueError(f"No directories found in {dir}")
|
48 |
+
|
49 |
+
latest_dir = max(dirs, key=lambda x: int(x))
|
50 |
+
return os.path.join(dir, latest_dir)
|
51 |
+
|
52 |
+
def get_latest_html_file(directory: str) -> str:
|
53 |
+
"""
|
54 |
+
Get the latest HTML file in the given directory.
|
55 |
+
|
56 |
+
Args:
|
57 |
+
directory (str): The directory to search for the latest HTML file.
|
58 |
+
|
59 |
+
Returns:
|
60 |
+
str: The path to the latest HTML
|
61 |
+
"""
|
62 |
+
|
63 |
+
html_files = [f for f in os.listdir(directory) if f.endswith(".html")]
|
64 |
+
if not html_files:
|
65 |
+
return None
|
66 |
+
|
67 |
+
latest_file = max(html_files, key=lambda x: int(os.path.splitext(x)[0]))
|
68 |
+
return os.path.join(directory, latest_file)
|
save.py
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from hashlib import md5
|
2 |
+
import json
|
3 |
+
import os
|
4 |
+
from dotenv import load_dotenv
|
5 |
+
|
6 |
+
load_dotenv()
|
7 |
+
|
8 |
+
|
9 |
+
def save_product_spec(url: str, product_spec: dict) -> bool:
|
10 |
+
"""
|
11 |
+
Save the product specification to the cache.
|
12 |
+
|
13 |
+
Args:
|
14 |
+
url (str): The URL of the product.
|
15 |
+
product_spec (dict): The product specification to save.
|
16 |
+
|
17 |
+
Returns:
|
18 |
+
bool: True if the product specification was saved successfully in the cache location, False otherwise.
|
19 |
+
"""
|
20 |
+
|
21 |
+
filename = md5(url.encode()).hexdigest()
|
22 |
+
filename = f"{filename}.json"
|
23 |
+
|
24 |
+
filepath = os.path.join(os.getenv("PROD_SPEC_DIR", "prod_spec"), filename)
|
25 |
+
try:
|
26 |
+
with open(filepath, "w") as f:
|
27 |
+
json.dump(product_spec, f, ensure_ascii=False, indent=2)
|
28 |
+
return True
|
29 |
+
except Exception as e:
|
30 |
+
return False
|
31 |
+
|
32 |
+
|
33 |
+
if __name__ == "__main__":
|
34 |
+
url = "https://comfy.ua/ua/smartfon/apple-iphone-13-128"
|
35 |
+
|
36 |
+
product_spec = {
|
37 |
+
"Діагональ дисплея": '6,7"',
|
38 |
+
"Тип екрану": "Super Retina XDR",
|
39 |
+
"Модель процесора": "Apple A14 Bionic",
|
40 |
+
"Основна камера": "12 Мп",
|
41 |
+
"Ємність акумулятора": "3687 мАг",
|
42 |
+
"name": "Смартфон Apple iPhone 12 Pro Max 256Gb Graphite (REF, A)",
|
43 |
+
"price": "29 499 ₴",
|
44 |
+
}
|
45 |
+
|
46 |
+
print(save_product_spec(url, product_spec))
|