File size: 9,012 Bytes
b776a3d c50c4ad b776a3d c50c4ad b776a3d c15b5bc b776a3d c15b5bc b776a3d c15b5bc b776a3d c15b5bc b776a3d a209729 b776a3d a209729 b776a3d a209729 b776a3d a209729 b776a3d 78e9173 a209729 78e9173 b776a3d a209729 b776a3d 78e9173 b776a3d a209729 b776a3d a209729 b776a3d 78e9173 b776a3d d2b0cae c50c4ad ce0ad53 78e9173 c50c4ad ce0ad53 78e9173 c50c4ad ce0ad53 78e9173 c50c4ad ce0ad53 78e9173 c50c4ad ce0ad53 78e9173 c50c4ad ce0ad53 78e9173 a209729 78e9173 c50c4ad ce0ad53 c50c4ad ce0ad53 78e9173 c50c4ad 6e2590e d2b0cae ce0ad53 b776a3d c50c4ad | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | import gradio as gr
import json
from dataclasses import dataclass, field, asdict
from typing import List, Dict, Any, Tuple, TypedDict, Annotated
# ... (所有数据结构和 Manager 类的代码保持不变) ...
@dataclass
class Entity: name: str; entityType: str; observations: List[str] = field(default_factory=list)
@dataclass
class Relation: from_entity: str; to_entity: str; relationType: str
@dataclass
class KnowledgeGraph: entities: Dict[str, Entity] = field(default_factory=dict); relations: List[Relation] = field(default_factory=list)
class KnowledgeGraphManager:
def __init__(self): self.graph = KnowledgeGraph(); print("Initialized a new, empty in-memory knowledge graph.")
def create_entities(self, entities_data: List[Dict]) -> List[Entity]:
new_entities = []; [ (new_entity := Entity(**e_data), self.graph.entities.update({e_data['name']: new_entity}), new_entities.append(new_entity)) for e_data in entities_data if e_data['name'] not in self.graph.entities]; return new_entities
def create_relations(self, relations_data: List[Dict]) -> List[Relation]:
new_relations = []; existing = {(r.from_entity, r.to_entity, r.relationType) for r in self.graph.relations}; [ (r_data.update({'from_entity': r_data.pop('from'), 'to_entity': r_data.pop('to')}), (new_relation := Relation(**r_data), self.graph.relations.append(new_relation), new_relations.append(new_relation))) for r_data in relations_data if (r_data['from'], r_data['to'], r_data['relationType']) not in existing]; return new_relations
def add_observations(self, observations_data: List[Dict]) -> List[Dict]:
results = []; [ (entity := self.graph.entities.get(o_data['entityName']), ( (new_obs := [obs for obs in o_data['contents'] if obs not in entity.observations]), entity.observations.extend(new_obs), results.append({"entityName": entity.name, "addedObservations": new_obs}) ) if entity else (_ for _ in ()).throw(ValueError(f"Entity with name {o_data['entityName']} not found"))) for o_data in observations_data]; return results
def delete_entities(self, entity_names: List[str]) -> None:
to_delete = set(entity_names); self.graph.entities = {n: e for n, e in self.graph.entities.items() if n not in to_delete}; self.graph.relations = [r for r in self.graph.relations if r.from_entity not in to_delete and r.to_entity not in to_delete]
def delete_observations(self, deletions_data: List[Dict]) -> None:
for d in deletions_data:
if (entity := self.graph.entities.get(d['entityName'])):
obs_to_delete = set(d['observations']); entity.observations = [obs for obs in entity.observations if obs not in obs_to_delete]
def delete_relations(self, relations_data: List[Dict]) -> None:
to_delete = {(r.get('from'), r.get('to'), r.get('relationType')) for r in relations_data}; self.graph.relations = [r for r in self.graph.relations if (r.from_entity, r.to_entity, r.relationType) not in to_delete]
def read_graph(self) -> Dict:
return {"entities": [asdict(e) for e in self.graph.entities.values()], "relations": [{"from": r.from_entity, "to": r.to_entity, "relationType": r.relationType} for r in self.graph.relations]}
def search_nodes(self, query: str) -> Dict:
q_lower = query.lower(); f_entities = [e for e in self.graph.entities.values() if q_lower in e.name.lower() or q_lower in e.entityType.lower() or any(q_lower in obs.lower() for obs in e.observations)]; f_names = {e.name for e in f_entities}; f_relations = [r for r in self.graph.relations if r.from_entity in f_names and r.to_entity in f_names]; return {"entities": [asdict(e) for e in f_entities], "relations": [{"from": r.from_entity, "to": r.to_entity, "relationType": r.relationType} for r in f_relations]}
def open_nodes(self, names: List[str]) -> Dict:
names_set = set(names); f_entities = [e for n, e in self.graph.entities.items() if n in names_set]; f_names = {e.name for e in f_entities}; f_relations = [r for r in self.graph.relations if r.from_entity in f_names and r.to_entity in f_names]; return {"entities": [asdict(e) for e in f_entities], "relations": [{"from": r.from_entity, "to": r.to_entity, "relationType": r.relationType} for r in f_relations]}
kg_manager = KnowledgeGraphManager()
class CreateEntitiesPayload(TypedDict): entities: List[Dict]
class CreateRelationsPayload(TypedDict): relations: List[Dict]
class AddObservationsPayload(TypedDict): observations: List[Dict]
class DeleteEntitiesPayload(TypedDict): entityNames: List[str]
class DeleteObservationsPayload(TypedDict): deletions: List[Dict]
class DeleteRelationsPayload(TypedDict): relations: List[Dict]
class SearchNodesPayload(TypedDict): query: str
class OpenNodesPayload(TypedDict): names: List[str]
def create_entities(payload: Annotated[CreateEntitiesPayload, "一个包含'entities'键的JSON对象。'entities'的值是一个实体对象的列表。"]) -> str:
"""在知识图谱中创建多个新实体。"""
new_entities = kg_manager.create_entities(payload['entities'])
return json.dumps([asdict(e) for e in new_entities], indent=2)
def create_relations(payload: Annotated[CreateRelationsPayload, "一个包含'relations'键的JSON对象。'relations'的值是一个关系对象的列表。"]) -> str:
"""在知识图谱中的实体之间创建多个新关系。"""
new_relations = kg_manager.create_relations(payload['relations'])
return json.dumps([{"from": r.from_entity, "to": r.to_entity, "relationType": r.relationType} for r in new_relations], indent=2)
# ... (所有其他API函数的定义也使用 Annotated[TypedDict, "description"] 格式) ...
def add_observations(payload: Annotated[AddObservationsPayload, "一个包含'observations'键的JSON对象。'observations'的值是一个观察记录对象的列表。"]) -> str:
"""向知识图ppu中已存在的实体添加新的观察记录。"""
results = kg_manager.add_observations(payload['observations'])
return json.dumps(results, indent=2)
def delete_entities(payload: Annotated[DeleteEntitiesPayload, "一个包含'entityNames'键的JSON对象。'entityNames'的值是一个实体名称的列表。"]) -> str:
"""从知识图谱中删除多个实体及其相关联的关系。"""
kg_manager.delete_entities(payload['entityNames'])
return "Entities and their relations deleted successfully."
def delete_observations(payload: Annotated[DeleteObservationsPayload, "一个包含'deletions'键的JSON对象。'deletions'的值是一个删除指令的列表。"]) -> str:
"""从知识图谱中的实体删除特定的观察记录。"""
kg_manager.delete_observations(payload['deletions'])
return "Observations deleted successfully."
def delete_relations(payload: Annotated[DeleteRelationsPayload, "一个包含'relations'键的JSON对象。'relations'的值是一个要删除的关系对象的列表。"]) -> str:
"""从知识图谱中删除多个关系。"""
kg_manager.delete_relations(payload['relations'])
return "Relations deleted successfully."
def read_graph() -> Dict:
"""读取并返回整个知识图谱。此函数不需要参数。"""
return kg_manager.read_graph()
def search_nodes(payload: Annotated[SearchNodesPayload, "一个包含'query'键的JSON对象。'query'的值是用于搜索的字符串。"]) -> Dict:
"""根据查询词在知识图谱中搜索节点。"""
return kg_manager.search_nodes(payload['query'])
def open_nodes(payload: Annotated[OpenNodesPayload, "一个包含'names'键的JSON对象。'names'的值是一个要检索的实体名称的列表。"]) -> Dict:
"""通过名称打开知识图谱中的特定节点。"""
return kg_manager.open_nodes(payload['names'])
with gr.Blocks() as app:
gr.Markdown("MCP Server is running. This UI is intentionally blank.", visible=True)
with gr.Row(visible=False):
json_input = gr.JSON(value={}); generic_output = gr.JSON(); dummy_btn = gr.Button()
dummy_btn.click(fn=create_entities, inputs=json_input, outputs=generic_output, api_name="create_entities")
dummy_btn.click(fn=create_relations, inputs=json_input, outputs=generic_output, api_name="create_relations")
dummy_btn.click(fn=add_observations, inputs=json_input, outputs=generic_output, api_name="add_observations")
dummy_btn.click(fn=delete_entities, inputs=json_input, outputs=generic_output, api_name="delete_entities")
dummy_btn.click(fn=delete_observations, inputs=json_input, outputs=generic_output, api_name="delete_observations")
dummy_btn.click(fn=delete_relations, inputs=json_input, outputs=generic_output, api_name="delete_relations")
dummy_btn.click(fn=read_graph, inputs=None, outputs=generic_output, api_name="read_graph")
dummy_btn.click(fn=search_nodes, inputs=json_input, outputs=generic_output, api_name="search_nodes")
dummy_btn.click(fn=open_nodes, inputs=json_input, outputs=generic_output, api_name="open_nodes")
if __name__ == "__main__":
app.launch(mcp_server=True) |