1+ import json
2+ import re
13from typing import List
24
35import gradio as gr
46
57from graphgen .bases .base_storage import BaseGraphStorage
68from graphgen .bases .datatypes import Chunk
79from graphgen .models import OpenAIClient
10+ from graphgen .templates import PROTEIN_ANCHOR_PROMPT , PROTEIN_KG_EXTRACTION_PROMPT
11+ from graphgen .utils import (
12+ detect_main_language ,
13+ handle_single_entity_extraction ,
14+ handle_single_relationship_extraction ,
15+ logger ,
16+ run_concurrent ,
17+ split_string_by_multi_markers ,
18+ )
819
920
1021async def build_mo_kg (
@@ -21,9 +32,89 @@ async def build_mo_kg(
2132 :param progress_bar: Gradio progress bar to show the progress of the extraction
2233 :return:
2334 """
24- # TODO: implement multi-omics KG building logic here
25- print ("llm_client:" , llm_client )
26- print ("kg_instance:" , kg_instance )
27- print ("chunks:" , chunks )
28- print ("progress_bar:" , progress_bar )
29- return kg_instance
35+
36+ async def extract_mo_info (chunk : Chunk ):
37+ content = chunk .content
38+ language = detect_main_language (content )
39+ prompt = PROTEIN_ANCHOR_PROMPT [language ].format (chunk = content )
40+ result = await llm_client .generate_answer (prompt )
41+ try :
42+ json_result = json .loads (result )
43+ return json_result
44+ except json .JSONDecodeError :
45+ logger .warning ("Failed to parse JSON from LLM response: %s" , result )
46+ return {}
47+
48+ results = await run_concurrent (
49+ extract_mo_info ,
50+ chunks ,
51+ desc = "Extracting multi-omics anchoring information from chunks" ,
52+ unit = "chunk" ,
53+ progress_bar = progress_bar ,
54+ )
55+ # Merge results
56+ from collections import defaultdict
57+
58+ bags = defaultdict (set )
59+ for item in results :
60+ for k , v in item .items ():
61+ if v is not None and str (v ).strip ():
62+ bags [k ].add (str (v ).strip ())
63+
64+ merged = {
65+ k : " | " .join (sorted (v )) if len (v ) > 1 else next (iter (v ))
66+ for k , v in bags .items ()
67+ }
68+
69+ # TODO: search database for more info
70+ # try:
71+ # search_results = await search(merged["Protein accession or ID"])
72+ # except Exception as e:
73+ # logger.warning("Failed to search for protein info: %s", e)
74+ # search_results = {}
75+
76+ # 组织成文本
77+ mo_text = "\n " .join ([f"{ k } : { v } " for k , v in merged .items ()])
78+ lang = detect_main_language (mo_text )
79+ prompt = PROTEIN_KG_EXTRACTION_PROMPT [lang ].format (
80+ input_text = mo_text ,
81+ ** PROTEIN_KG_EXTRACTION_PROMPT ["FORMAT" ],
82+ )
83+ kg_output = await llm_client .generate_answer (prompt )
84+
85+ logger .debug ("Image chunk extraction result: %s" , kg_output )
86+
87+ # parse the result
88+ records = split_string_by_multi_markers (
89+ kg_output ,
90+ [
91+ PROTEIN_KG_EXTRACTION_PROMPT ["FORMAT" ]["record_delimiter" ],
92+ PROTEIN_KG_EXTRACTION_PROMPT ["FORMAT" ]["completion_delimiter" ],
93+ ],
94+ )
95+
96+ print (records )
97+ raise NotImplementedError
98+
99+ nodes = defaultdict (list )
100+ edges = defaultdict (list )
101+
102+ for record in records :
103+ match = re .search (r"\((.*)\)" , record )
104+ if not match :
105+ continue
106+ inner = match .group (1 )
107+
108+ attributes = split_string_by_multi_markers (
109+ inner , [PROTEIN_KG_EXTRACTION_PROMPT ["FORMAT" ]["tuple_delimiter" ]]
110+ )
111+
112+ entity = await handle_single_entity_extraction (attributes , "temp" )
113+ if entity is not None :
114+ nodes [entity ["entity_name" ]].append (entity )
115+ continue
116+
117+ relation = await handle_single_relationship_extraction (attributes , "temp" )
118+ if relation is not None :
119+ key = (relation ["src_id" ], relation ["tgt_id" ])
120+ edges [key ].append (relation )
0 commit comments