د LLMGraphTransformer تطبیق سره توپیر دا دی چې ټول نوډ یا د اړیکو ملکیت اختیاري دي، نو ټول نوډونه به د description ملکیت ونه لري. که موږ وغواړو، موږ کولی شو یو دودیز استخراج تعریف کړو ترڅو د اجباري description ملکیت ولري، مګر موږ به دا په دې تطبیق کې پریږدو.
موږ به د ګراف استخراج ګړندي کولو لپاره غوښتنې موازي کړو او پایلې به Neo4j ته ذخیره کړو:
MAX_WORKERS = 10 NUM_ARTICLES = 2000 graph_documents = [] with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor: # Submitting all tasks and creating a list of future objects futures = [ executor.submit(process_text, f"{row['title']} {row['text']}") for i, row in news.head(NUM_ARTICLES).iterrows() ] for future in tqdm( as_completed(futures), total=len(futures), desc="Processing documents" ): graph_document = future.result() graph_documents.extend(graph_document) graph.add_graph_documents( graph_documents, baseEntityLabel=True, include_source=True )
په دې مثال کې، موږ د 2,000 مقالو څخه د ګراف معلومات راټولوو او پایلې یې Neo4j ته ذخیره کوو. موږ شاوخوا 13,000 ادارې او 16,000 اړیکې استخراج کړې. دلته په ګراف کې د استخراج شوي سند یوه بیلګه ده.
پدې مرحله کې ، لیکوالان هوریستیک معرفي کوي ترڅو پریکړه وکړي چې ایا د ګراف معلومات له یو څخه ډیر پاس کې استخراج کړي. د سادگي لپاره، موږ به یوازې یو پاس ترسره کړو. په هرصورت، که موږ وغواړو څو څو پاسونه ترسره کړو، موږ کولی شو د استخراج لومړنۍ پایلې د خبرو اترو تاریخ په توګه وساتو او په ساده ډول ، او دا باید نور استخراج کړي، لکه د GraphRAG لیکوالان یې کوي.
مخکې، ما یادونه وکړه چې د متن اندازه څومره حیاتي ده او دا څنګه د استخراج شویو ادارو شمیر اغیزه کوي. له هغه ځایه چې موږ کوم اضافي متن ټوټه کول نه دي ترسره کړي، موږ کولی شو د استخراج شویو ادارو ویش د متن د اندازې پر بنسټ ارزونه وکړو:
entity_dist = graph.query( """ MATCH (d:Document) RETURN d.text AS text, count {(d)-[:MENTIONS]->()} AS entity_count """ ) entity_dist_df = pd.DataFrame.from_records(entity_dist) entity_dist_df["token_count"] = [ num_tokens_from_string(str(el)) for el in entity_dist_df["text"] ] # Scatter plot with regression line sns.lmplot( x="token_count", y="entity_count", data=entity_dist_df, line_kws={"color": "red"} ) plt.title("Entity Count vs Token Count Distribution") plt.xlabel("Token Count") plt.ylabel("Entity Count") plt.show()
د توزیع پلاټ ښیي چې پداسې حال کې چې یو مثبت رجحان شتون لري، د سره کرښې لخوا اشاره شوې، اړیکه فرعي ده. ډیری ډیټا پوائنټونه د ټیټ ادارو شمیرو کې کلستر کیږي ، حتی لکه څنګه چې د نښې شمیرې ډیریږي. دا په ګوته کوي چې د استخراج شویو ادارو شمیر د متن د ټوټو د اندازې سره متناسب اندازه نه کوي. که څه هم ځینې بهرنیان شتون لري، عمومي نمونه ښیي چې د لوړې نښې شمیرې په دوامداره توګه د لوړو ادارو شمیرو لامل نه کیږي. دا د لیکوالانو موندنه تاییدوي چې د ټیټ متن ټوټې اندازه به نور معلومات استخراج کړي.
ما دا هم فکر کاوه چې دا به په زړه پوري وي چې د جوړ شوي ګراف د نوډ درجې توزیع معاینه کړئ. لاندې کوډ د نوډ درجې توزیع ترلاسه کوي او لید یې کوي:
degree_dist = graph.query( """ MATCH (e:__Entity__) RETURN count {(e)-[:!MENTIONS]-()} AS node_degree """ ) degree_dist_df = pd.DataFrame.from_records(degree_dist) # Calculate mean and median mean_degree = np.mean(degree_dist_df['node_degree']) percentiles = np.percentile(degree_dist_df['node_degree'], [25, 50, 75, 90]) # Create a histogram with a logarithmic scale plt.figure(figsize=(12, 6)) sns.histplot(degree_dist_df['node_degree'], bins=50, kde=False, color='blue') # Use a logarithmic scale for the x-axis plt.yscale('log') # Adding labels and title plt.xlabel('Node Degree') plt.ylabel('Count (log scale)') plt.title('Node Degree Distribution') # Add mean, median, and percentile lines plt.axvline(mean_degree, color='red', linestyle='dashed', linewidth=1, label=f'Mean: {mean_degree:.2f}') plt.axvline(percentiles[0], color='purple', linestyle='dashed', linewidth=1, label=f'25th Percentile: {percentiles[0]:.2f}') plt.axvline(percentiles[1], color='orange', linestyle='dashed', linewidth=1, label=f'50th Percentile: {percentiles[1]:.2f}') plt.axvline(percentiles[2], color='yellow', linestyle='dashed', linewidth=1, label=f'75th Percentile: {percentiles[2]:.2f}') plt.axvline(percentiles[3], color='brown', linestyle='dashed', linewidth=1, label=f'90th Percentile: {percentiles[3]:.2f}') # Add legend plt.legend() # Show the plot plt.show()
د نوډ درجې توزیع د بریښنا قانون نمونه تعقیبوي، دا په ګوته کوي چې ډیری نوډونه خورا لږ ارتباط لري پداسې حال کې چې یو څو نوډونه خورا ډیر تړلي دي. منځنۍ درجه 2.45 ده، او منځنۍ درجه 1.00 ده، دا ښیي چې له نیمایي څخه زیات نوډونه یوازې یو تړاو لري. ډیری نوډونه (75 سلنه) دوه یا لږ اړیکې لري، او 90 سلنه پنځه یا لږ څه لري. دا توزیع د ډیری ریښتیني نړۍ شبکو لپاره ځانګړی دی ، چیرې چې لږ شمیر مرکزونه ډیری اړیکې لري ، او ډیری نوډونه لږ دي.
څرنګه چې دواړه نوډ او د اړیکو توضیحات لازمي ملکیتونه ندي، موږ به دا هم وڅیړو چې څومره استخراج شوي:
graph.query(""" MATCH (n:`__Entity__`) RETURN "node" AS type, count(*) AS total_count, count(n.description) AS non_null_descriptions UNION ALL MATCH (n)-[r:!MENTIONS]->() RETURN "relationship" AS type, count(*) AS total_count, count(r.description) AS non_null_descriptions """)
پایلې ښیې چې د 12,994 څخه 5,926 نوډونه (45.6 سلنه) د توضیح ملکیت لري. له بلې خوا، له 15,921 څخه یوازې 5,569 اړیکې (35 سلنه) دا ډول ملکیت لري.
په یاد ولرئ چې د LLMs احتمالي طبیعت له امله ، شمیرې په مختلف منډو او مختلف سرچینې ډیټا ، LLMs ، او اشارو کې توپیر کولی شي.
د ادارې قرارداد
د ادارې ریزولوشن (د نقل کولو) د پوهې ګرافونو رامینځته کولو کې خورا مهم دی ځکه چې دا ډاډ ورکوي چې هره اداره په ځانګړي او دقیق ډول نمایش کیږي ، د نقلونو مخه نیسي او د ریکارډونو یوځای کول چې ورته ریښتیني نړۍ ته راجع کیږي. دا پروسه په ګراف کې د معلوماتو بشپړتیا او ثبات ساتلو لپاره اړینه ده. د ادارې ریزولوشن پرته، د پوهې ګرافونه به د ټوټې او متناسب معلوماتو سره مخ شي، چې د غلطیو او غیر باوري بصیرت لامل کیږي.
دا انځور ښیي چې څنګه د ریښتینې نړۍ یو واحد وجود په مختلفو اسنادو کې او په پایله کې، زموږ په ګراف کې د یو څه مختلف نومونو لاندې ښکاره کیدی شي.
برسېره پردې، لږ معلومات د ادارې حل پرته د پام وړ مسله کیږي. د مختلفو سرچینو څخه نیمګړی یا جزوی معلومات کولی شي د معلوماتو د ویشل شوي او منحل شوي ټوټو لامل شي، چې دا ستونزمن کوي چې د ادارو یو همغږي او هراړخیز پوهه رامینځته کړي. د ادارې دقیق حل دا د ډیټا راټولولو ، تشو ډکولو ، او د هرې ادارې متحد لید رامینځته کولو سره حل کوي.
د متن سرایت پرتله کول د احتمالي نقلونو موندلو کې مرسته کوي ، مګر دا یوازې د ادارې حل پروسې برخه ده. د مثال په توګه، ګوګل او ایپل د سرایت کولو ځای کې خورا نږدې دي (0.96 کوزین ورته والی د ada-002 ایمبیډینګ ماډل په کارولو سره). ورته د BMW او مرسډیز بینز (0.97 کوزین ورته والی) لپاره ځي. د لوړ متن سرایت ورته والی یو ښه پیل دی، مګر موږ کولی شو دا ښه کړو. له همدې امله، موږ به یو اضافي فلټر اضافه کړو چې یوازې د دریو یا لږ متن فاصله سره د کلمو جوړه اجازه ورکوي (په دې معنی چې یوازې حروف بدل کیدی شي):
word_edit_distance = 3 potential_duplicate_candidates = graph.query( """MATCH (e:`__Entity__`) WHERE size(e.id) > 3 // longer than 3 characters WITH e.wcc AS community, collect(e) AS nodes, count(*) AS count WHERE count > 1 UNWIND nodes AS node // Add text distance WITH distinct [n IN nodes WHERE apoc.text.distance(toLower(node.id), toLower(n.id)) < $distance OR node.id CONTAINS n.id | n.id] AS intermediate_results WHERE size(intermediate_results) > 1 WITH collect(intermediate_results) AS results // combine groups together if they share elements UNWIND range(0, size(results)-1, 1) as index WITH results, index, results[index] as result WITH apoc.coll.sort(reduce(acc = result, index2 IN range(0, size(results)-1, 1) | CASE WHEN index <> index2 AND size(apoc.coll.intersection(acc, results[index2])) > 0 THEN apoc.coll.union(acc, results[index2]) ELSE acc END )) as combinedResult WITH distinct(combinedResult) as combinedResult // extra filtering WITH collect(combinedResult) as allCombinedResults UNWIND range(0, size(allCombinedResults)-1, 1) as combinedResultIndex WITH allCombinedResults[combinedResultIndex] as combinedResult, combinedResultIndex, allCombinedResults WHERE NOT any(x IN range(0,size(allCombinedResults)-1,1) WHERE x <> combinedResultIndex AND apoc.coll.containsAll(allCombinedResults[x], combinedResult) ) RETURN combinedResult """, params={'distance': word_edit_distance})
دا د سایفر بیان یو څه ډیر ښکیل دی، او د دې تفسیر د دې بلاګ پوسټ له ساحې څخه بهر دی. تاسو کولی شئ تل د LLM څخه د دې تشریح کولو غوښتنه وکړئ.
برسیره پردې، د فاصلې کټ آف کلمه کیدای شي د یوې شمیرې پر ځای د کلمې د اوږدوالي فعالیت وي او پلي کول کیدای شي د اندازې وړ وي.
هغه څه چې مهم دي دا دي چې دا د احتمالي ادارو ګروپونه تولیدوي چې موږ یې یوځای کول غواړو. دلته د ضم کولو احتمالي نوډونو لیست دی:
system_prompt = """You are a data processing assistant. Your task is to identify duplicate entities in a list and decide which of them should be merged. The entities might be slightly different in format or content, but essentially refer to the same thing. Use your analytical skills to determine duplicates. Here are the rules for identifying duplicates: 1. Entities with minor typographical differences should be considered duplicates. 2. Entities with different formats but the same content should be considered duplicates. 3. Entities that refer to the same real-world object or concept, even if described differently, should be considered duplicates. 4. If it refers to different numbers, dates, or products, do not merge results """ user_template = """ Here is the list of entities to process: {entities} Please identify duplicates, merge them, and provide the merged list. """
دلته، موږ به محصول list of lists په توګه تعریف کړو، چیرته چې هر داخلي لیست هغه ادارې لري چې باید یوځای شي. دا جوړښت د سناریوګانو اداره کولو لپاره کارول کیږي چیرې چې د بیلګې په توګه، ان پټ ممکن وي [Sony, Sony Inc, Google, Google Inc] . په داسې حاالتو کې، تاسو غواړئ "سوني" او "سوني شرکت" د "ګوګل" او "ګوګل شرکت" څخه جلا جلا کړئ.
class DuplicateEntities(BaseModel): entities: List[str] = Field( description="Entities that represent the same object or real-world entity and should be merged" ) class Disambiguate(BaseModel): merge_entities: Optional[List[DuplicateEntities]] = Field( description="Lists of entities that represent the same object or real-world entity and should be merged" ) extraction_llm = ChatOpenAI(model_name="gpt-4o").with_structured_output( Disambiguate )
بیا، موږ د LLM پرامپټ د جوړښت شوي محصول سره مدغم کوو ترڅو د LangChain Expression Language (LCEL) ترکیب په کارولو سره یو زنځیر رامینځته کړي او دا په یو disambiguate فعالیت کې ځای په ځای کړي.
extraction_chain = extraction_prompt | extraction_llm def entity_resolution(entities: List[str]) -> Optional[List[List[str]]]: return [ el.entities for el in extraction_chain.invoke({"entities": entities}).merge_entities ]
merged_entities = [] with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor: # Submitting all tasks and creating a list of future objects futures = [ executor.submit(entity_resolution, el['combinedResult']) for el in potential_duplicate_candidates ] for future in tqdm( as_completed(futures), total=len(futures), desc="Processing documents" ): to_merge = future.result() if to_merge: merged_entities.extend(to_merge)
خیال په زړه پوری دی. موږ لاهم د متن څخه د موضوع او اعتراض IDs یا نومونه استخراج کوو، کوم چې موږ ته اجازه راکوي چې اړیکې سمو ادارو سره وصل کړو، حتی کله چې ادارې د متن په څو برخو کې څرګندیږي. په هرصورت، اړیکې یو واحد ډول ته ندي کم شوي. پرځای یې، د اړیکو ډول په حقیقت کې یو وړیا متن دی چې موږ ته اجازه راکوي چې بډایه او ډیر مهم معلومات وساتو.
برسیره پردې، د ادارې معلومات د LLM په کارولو سره لنډیز شوي، موږ ته اجازه راکوي چې دا معلومات او ادارې د لا دقیقو لاسته راوړلو لپاره په اغیزمنه توګه داخل او شاخص کړو.
یو څوک استدلال کولی شي چې دا خورا بډایه او خورا مهم معلومات د اضافي ، احتمالي خپلسري ، نوډ او اړیکو ملکیتونو اضافه کولو سره هم ساتل کیدی شي. د خپلسري نوډ او اړیکو ملکیتونو سره یوه مسله دا ده چې دا به سخت وي چې معلومات په دوامداره توګه استخراج کړي ځکه چې LLM ممکن د ملکیت مختلف نومونه وکاروي یا په هر اجرا کولو مختلف توضیحاتو تمرکز وکړي.
ځینې دا ستونزې د اضافي ډول او توضیحاتو معلوماتو سره د مخکیني تعریف شوي ملکیت نومونو په کارولو سره حل کیدی شي. په دې حالت کې، تاسو به د موضوع متخصص ته اړتیا ولرئ ترڅو د دې ملکیتونو په تعریف کې مرسته وکړي، د LLM لپاره لږ ځای پریږدي ترڅو د وړاندې شوي توضیحاتو څخه بهر کوم مهم معلومات راوباسي.
د 1,000 څخه زیاتو ټولنو لیدل سخت دي؛ حتی د هر یو لپاره د رنګونو غوره کول په عملي توګه ناممکن دي. په هرصورت، دوی د ښه هنري نندارې لپاره جوړوي.
د دې په جوړولو سره، موږ به د هرې ټولنې لپاره یو جلا نوډ جوړ کړو او د یو بل سره تړلي ګراف په توګه به د دوی درجه بندي جوړښت استازیتوب وکړو. وروسته، موږ به د ټولنې لنډیز او نور ځانګړتیاوې د نوډ ملکیتونو په توګه ذخیره کړو.
graph.query(""" MATCH (e:`__Entity__`) UNWIND range(0, size(e.communities) - 1 , 1) AS index CALL { WITH e, index WITH e, index WHERE index = 0 MERGE (c:`__Community__` {id: toString(index) + '-' + toString(e.communities[index])}) ON CREATE SET c.level = index MERGE (e)-[:IN_COMMUNITY]->(c) RETURN count(*) AS count_0 } CALL { WITH e, index WITH e, index WHERE index > 0 MERGE (current:`__Community__` {id: toString(index) + '-' + toString(e.communities[index])}) ON CREATE SET current.level = index MERGE (previous:`__Community__` {id: toString(index - 1) + '-' + toString(e.communities[index - 1])}) ON CREATE SET previous.level = index - 1 MERGE (previous)-[:IN_COMMUNITY]->(current) RETURN count(*) AS count_1 } RETURN count(*) """)
graph.query(""" MATCH (c:__Community__)<-[:IN_COMMUNITY*]-(:__Entity__)<-[:MENTIONS]-(d:Document) WITH c, count(distinct d) AS rank SET c.community_rank = rank; """)
راځئ چې د ټولنو شمیر او د دوی اندازې او مختلفې کچې په ډیر تفصیل سره وڅیړو:
community_size = graph.query( """ MATCH (c:__Community__)<-[:IN_COMMUNITY*]-(e:__Entity__) WITH c, count(distinct e) AS entities RETURN split(c.id, '-')[0] AS level, entities """ ) community_size_df = pd.DataFrame.from_records(community_size) percentiles_data = [] for level in community_size_df["level"].unique(): subset = community_size_df[community_size_df["level"] == level]["entities"] num_communities = len(subset) percentiles = np.percentile(subset, [25, 50, 75, 90, 99]) percentiles_data.append( [ level, num_communities, percentiles[0], percentiles[1], percentiles[2], percentiles[3], percentiles[4], max(subset) ] ) # Create a DataFrame with the percentiles percentiles_df = pd.DataFrame( percentiles_data, columns=[ "Level", "Number of communities", "25th Percentile", "50th Percentile", "75th Percentile", "90th Percentile", "99th Percentile", "Max" ], ) percentiles_df
په اصلي تطبیق کې، په هره کچه ټولنې لنډیز شوي. زموږ په قضیه کې، دا به 8,590 ټولنې وي او په پایله کې، 8,590 LLM زنګونه. زه به استدلال وکړم چې د ټولنې د تنظیمي جوړښت پورې اړه لري، د هرې کچې لنډیز ته اړتیا نلري. د مثال په توګه، د وروستي او راتلونکي څخه تر وروستي کچې توپیر یوازې څلور ټولنې دی (1,192 vs. 1,188). له همدې امله ، موږ به ډیری بې ځایه لنډیزونه رامینځته کړو. یو حل دا دی چې یو داسې تطبیق رامینځته کړي چې کولی شي په مختلفو کچو کې د ټولنو لپاره یو واحد لنډیز رامینځته کړي چې بدلون نه کوي؛ بل به دا وي چې د ټولنې درجه بندي له مینځه یوسي چې بدلون نه کوي.
همچنان، زه ډاډه نه یم که موږ غواړو یوازې د یو غړي سره ټولنې لنډیز کړو، ځکه چې دوی ممکن ډیر ارزښت یا معلومات چمتو نکړي. دلته، موږ به ټولنې په 0، 1، او 4 کچه لنډیز کړو. لومړی، موږ اړتیا لرو چې د دوی معلومات له ډیټابیس څخه ترلاسه کړو:
community_info = graph.query(""" MATCH (c:`__Community__`)<-[:IN_COMMUNITY*]-(e:__Entity__) WHERE c.level IN [0,1,4] WITH c, collect(e ) AS nodes WHERE size(nodes) > 1 CALL apoc.path.subgraphAll(nodes[0], { whitelistNodes:nodes }) YIELD relationships RETURN c.id AS communityId, [n in nodes | {id: n.id, description: n.description, type: [el in labels(n) WHERE el <> '__Entity__'][0]}] AS nodes, [r in relationships | {start: startNode(r).id, type: type(r), end: endNode(r).id, description: r.description}] AS rels """)
لیکوالانو نه یوازې ټولنې لنډیز کړي بلکې د هرې یوې لپاره موندنې هم رامینځته کړي. یوه موندنه د یوې ځانګړې پیښې یا د معلوماتو برخې په اړه د لنډ معلومات په توګه تعریف کیدی شي. داسې یوه بیلګه:
"summary": "Abila City Park as the central location", "explanation": "Abila City Park is the central entity in this community, serving as the location for the POK rally. This park is the common link between all other entities, suggesting its significance in the community. The park's association with the rally could potentially lead to issues such as public disorder or conflict, depending on the nature of the rally and the reactions it provokes. [records: Entities (5), Relationships (37, 38, 39, 40)]"
زما هوښیارتیا وړاندیز کوي چې یوازې د یو واحد پاس سره د موندنو استخراج ممکن دومره جامع نه وي لکه څنګه چې موږ ورته اړتیا لرو، لکه د ادارو او اړیکو استخراج.
برسېره پردې، ما د دوی په کوډ کې د محلي یا نړیوال لټون بیرته اخیستونکو کې د دوی د کارولو هیڅ حواله یا مثال ندی موندلی. د پایلې په توګه، موږ به په دې مثال کې د موندنو د استخراج څخه ډډه وکړو. یا، لکه څنګه چې اکادمیکان اکثرا دا بیانوي: دا تمرین لوستونکي ته پریښودل کیږي. سربیره پردې، موږ هم پریږدو، کوم چې په لومړي نظر کې موندنو ته ورته ښکاري.
community_template = """Based on the provided nodes and relationships that belong to the same graph community, generate a natural language summary of the provided information: {community_info} Summary:""" # noqa: E501 community_prompt = ChatPromptTemplate.from_messages( [ ( "system", "Given an input triples, generate the information summary. No pre-amble.", ), ("human", community_template), ] ) community_chain = community_prompt | llm | StrOutputParser()
یوازینی شی پاتې دی چې د ټولنې نمایندګۍ په تارونو بدل کړئ ترڅو د JSON ټوکن سر څخه مخنیوی کولو سره د ټوکنونو شمیر کم کړئ او زنځیر د فنکشن په توګه وپلټئ:
def prepare_string(data): nodes_str = "Nodes are:\n" for node in data['nodes']: node_id = node['id'] node_type = node['type'] if 'description' in node and node['description']: node_description = f", description: {node['description']}" else: node_description = "" nodes_str += f"id: {node_id}, type: {node_type}{node_description}\n" rels_str = "Relationships are:\n" for rel in data['rels']: start = rel['start'] end = rel['end'] rel_type = rel['type'] if 'description' in rel and rel['description']: description = f", description: {rel['description']}" else: description = "" rels_str += f"({start})-[:{rel_type}]->({end}){description}\n" return nodes_str + "\n" + rels_str def process_community(community): stringify_info = prepare_string(community) summary = community_chain.invoke({'community_info': stringify_info}) return {"community": community['communityId'], "summary": summary}
summaries = [] with ThreadPoolExecutor() as executor: futures = {executor.submit(process_community, community): community for community in community_info} for future in tqdm(as_completed(futures), total=len(futures), desc="Processing communities"): summaries.append(future.result())
یو اړخ چې ما یې یادونه نه ده کړې هغه دا ده چې لیکوالان د ټولنې معلوماتو داخلولو په وخت کې د شرایطو اندازې څخه ډیر احتمالي مسله هم په ګوته کوي. لکه څنګه چې ګراف پراخیږي، ټولنې هم د پام وړ وده کولی شي. زموږ په قضیه کې، ترټولو لویه ټولنه 545 غړي لري. دې ته په پام سره چې GPT-4o د شرایطو اندازه له 100,000 ټوکنونو څخه زیاته ده، موږ پریکړه وکړه چې دا مرحله پریږدو.
یو شی چې په واضح ډول نه دی ذکر شوی دا دی چې موږ کولی شو د جوړښت شوي ډیټا سرچینې هم په ګراف کې مدغم کړو؛ ان پټ باید یوازې په غیر منظم متن پورې محدود نه وي.
هغه څه چې زه په ځانګړې توګه د دوی د استخراج طریقې په اړه ستاینه کوم دا دی چې دوی د نوډونو او اړیکو دواړو لپاره توضیحات نیسي. توضیحات LLM ته اجازه ورکوي چې یوازې د نوډ IDs او اړیکو ډولونو ته د هرڅه کمولو په پرتله نور معلومات وساتي.
برسیره پردې، دوی ښیي چې د متن په اړه یو واحد استخراج ممکن ټول اړونده معلومات ونه نیسي او د اړتیا په صورت کې د ډیری پاسونو ترسره کولو لپاره منطق معرفي کړي. لیکوالان د ګراف ټولنو په اړه د لنډیزونو د ترسره کولو لپاره په زړه پورې نظر هم وړاندې کوي، موږ ته اجازه راکوي چې د ډیری ډیټا سرچینو په اوږدو کې کنډنډ شوي موضوعي معلومات سرایت او شاخص کړو.