SAP HANA Cloud Knowledge Graph Engine

SAP HANA Cloud Knowledge Graph Engine

SAP HANA Cloud Knowledge Graph 엔진을 LangChain에서 사용하는 방법을 안내할게요.

출처: 문서

본문

SAP HANA Cloud Knowledge Graph는 SAP HANA Cloud 데이터베이스 내에 완전히 통합된 지식 그래프 솔루션이에요.

설정 및 설치

사전 요구사항:

LangChain과 함께 SAP HANA Knowledge Graph Engine을 사용하려면 @sap/hana-langchain 패키지를 peer 의존성과 함께 설치하세요:

npm install @sap/hana-langchain @langchain/core@latest langchain@latest
import * as dotenv from 'dotenv';
// Load environment variables if needed
dotenv.config();

import hanaClient from "@sap/hana-client";

const connectionParams = {
  host: process.env.HANA_DB_ADDRESS,
  port: process.env.HANA_DB_PORT,
  user: process.env.HANA_DB_USER,
  password: process.env.HANA_DB_PASSWORD,
};
const client = hanaClient.createConnection(connectionParams);

// connect to hanaDB
await new Promise<void>((resolve, reject) => {
  client.connect((err: Error) => {
    // Use arrow function here
    if (err) {
      reject(err);
    } else {
      console.log("Connected to SAP HANA successfully.");
      resolve();
    }
  });
});

그런 다음 HanaRdfGraph 클래스를 임포트하세요.

import { HanaRdfGraph } from "@sap/hana-langchain";
// const graph = new HanaRdfGraph({ connection: client, autoExtractOntology: true });

HanaRdfGraph 인스턴스 생성

생성자는 다음을 요구해요:

  • connection: 활성 @sap/hana-client Connection 인스턴스
  • graphUri: RDF 데이터가 있는 명명된 그래프(또는 "DEFAULT")
  • 다음 중 하나:
    1. ontologyQuery: 스키마 트리플을 추출하는 SPARQL CONSTRUCT
    2. ontologyUri: 호스팅된 온톨로지 그래프 URI
    3. ontologyLocalFile + ontologyLocalFileFormat: 로컬 Turtle/RDF 파일
    4. autoExtractOntology: true (프로덕션 권장하지 않음—참고 참조)

graphUri vs. 온톨로지

  • graphUri: 인스턴스 데이터가 들어 있는 SAP HANA Cloud 인스턴스의 명명된 그래프 (때로는 100k+ 트리플). graphUri가 제공되지 않거나 "" 또는 "DEFAULT"로 주어지면 기본 그래프가 사용돼요.
  • 온톨로지: 클래스, 속성, 도메인, 범위, 라벨, 주석, 하위 클래스 관계를 설명하는 정제된 스키마(보통 ~50-100 트리플). 온톨로지는 SPARQL 생성과 결과 해석을 안내해요.

DEFAULT 그래프로 그래프 인스턴스 생성

DEFAULT 그래프에 대한 자세한 내용은 DEFAULT Graph 및 Named Graphs에서 확인할 수 있어요.

const graphOptions = {
    connection: client,
    autoExtractOntology: true
};
const graph = new HanaRdfGraph(graphOptions);

// need to initialize once an instance is created.
await graph.initialize(graphOptions);

// const graphOptions = {
//     connection: client,
//     graphUri: "DEFAULT",
//     autoExtractOntology: true
// };

// const graph = new HanaRdfGraph(graphOptions);
// await graph.initialize(graphOptions);

// const graphOptions = {
//     connection: client,
//     graphUri: "",
//     autoExtractOntology: true
// };

// const graph = new HanaRdfGraph(graphOptions);
// await graph.initialize(graphOptions);

graph_uri로 그래프 인스턴스 생성

const graphOptions = {
  connection: client,
  graphUri: "http://example.org/movies",
  autoExtractOntology: true,
};
const graph = new HanaRdfGraph(graphOptions);
await graph.initialize(graphOptions);

원격 ontology_uri로 그래프 인스턴스 생성

const graphOptions = {
    connection: client,
    ontologyUri: "<your_ontology_graph_uri>"
};
const graph = new HanaRdfGraph(graphOptions);
await graph.initialize(graphOptions);

커스텀 ontology_query로 그래프 인스턴스 생성

커스텀 CONSTRUCT 쿼리를 사용해 스키마 트리플을 선택적으로 추출하세요.

const ontologyQuery = `
  PPREFIX owl: <http://www.w3.org/2002/07/owl#>
  PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
  PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
  PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
  CONSTRUCT {?cls rdf:type owl:Class . ?cls rdfs:label ?clsLabel . ?rel rdf:type ?propertyType . ?rel rdfs:label ?relLabel . ?rel rdfs:domain ?domain . ?rel rdfs:range ?range .}
  FROM <kgdocu_movies>
  WHERE { # get properties
    {SELECT DISTINCT ?domain ?rel ?relLabel ?propertyType ?range
      WHERE {
        ?subj ?rel ?obj .
        ?subj a ?domain .
        OPTIONAL{?obj a ?rangeClass .}
        FILTER(?rel != rdf:type)
        BIND(IF(isIRI(?obj) = true, owl:ObjectProperty, owl:DatatypeProperty) AS ?propertyType)
        BIND(COALESCE(?rangeClass, DATATYPE(?obj)) AS ?range)
        BIND(STR(?rel) AS ?uriStr)       # Convert URI to string
        BIND(REPLACE(?uriStr, "^.*[/#]", "") AS ?relLabel)
      }}
      UNION { # get classes
        SELECT DISTINCT ?cls ?clsLabel
        WHERE {
            ?instance a/rdfs:subClassOf* ?cls .
            FILTER (isIRI(?cls)) .
            BIND(STR(?cls) AS ?uriStr)       # Convert URI to string
            BIND(REPLACE(?uriStr, "^.*[/#]", "") AS ?clsLabel)
        }
      }
   }
`;

// can provide the graph_uri param as well if needed
const graphOptions = {
    connection: client,
    ontologyQuery
};
const graph = new HanaRdfGraph(graphOptions);
await graph.initialize(graphOptions);

로컬 RDF 파일에서 온톨로지 로드

지원되는 RDF 형식: Turtle, N-Triples, Notation-3, Trig, N-Quads.

const graphOptions = {
  connection: client,
  ontologyLocalFile: "<your_ontology_file_path>", // e.g., "ontology.ttl"
  ontologyLocalFileFormat: "<your_ontology_file_format>", // e.g., "Turtle", "N-Triples", "Notation-3", "Trig", "N-Quads"
};
const graph = new HanaRdfGraph(graphOptions);
await graph.initialize(graphOptions);

온톨로지 자동 추출

(auto_extract_ontology=True): 인스턴스 데이터에서 직접 스키마 정보를 추론해요.

const graphOptions = {
  connection: client,
  graphUri: "<your_graph_uri>",
  autoExtractOntology: true,
};
const graph = new HanaRdfGraph(graphOptions);
await graph.initialize(graphOptions);

참고: 자동 추출은 프로덕션에 권장되지 않아요 — 일반적으로 rdfs:label, rdfs:comment, rdfs:subClassOf 같은 중요한 트리플을 생략해요.

SPARQL 쿼리 실행

query() 메서드로 데이터 그래프에서 임의의 SPARQL 쿼리(SELECT, ASK, CONSTRUCT 등)를 실행할 수 있어요.

이 함수는 다음 매개변수를 가져요:

  • query: SPARQL 쿼리 문자열.
  • content_type: 출력에 대한 응답 형식 (기본은 CSV)

각 형식에 대해 다음 문자열을 사용하세요.

  • CSV: "sparql-results+xml"
  • JSON: "sparql-results+json"
  • XML: "sparql-results+csv"
  • TSV: "sparql-results+tsv"

참고: CONSTRUCT와 ASK 쿼리는 각각 turtleboolean 형식을 반환해요.

Puppets 그래프에 일부 데이터를 삽입해 봅시다.

await new Promise<void>((resolve, reject) => {
  const sparqlQuery = `CALL SYS.SPARQL_EXECUTE(?, ?, ?, ?)`;
  client.prepare(sparqlQuery, (err: Error, stmt) => {
    if (err) {
      reject(err);
    } else {
      const query = `
      INSERT DATA {
        GRAPH <Puppets> {
            <P1> a <Puppet>; <name> "Ernie"; <show> "Sesame Street".
            <P2> a <Puppet>; <name> "Bert"; <show> "Sesame Street" .
            }
        }`;
      const params: HanaParameterList = {
        REQUEST: query,
        PARAMETER: "",
      };
      stmt?.exec(params, (err: Error) => {
        if (err) {
          reject(err);
        } else {
          resolve(stmt.getParameterValue(2));
        }
      });
    }
  });
});

그런 다음 Puppets 그래프에 대한 그래프 인스턴스를 생성해요.

const graphOptions = {
  connection: client,
  graphUri: "Puppets",
  autoExtractOntology: true,
};

// create a Graph instance from a source URI
const graph = new HanaRdfGraph(graphOptions);

// need to initialize once an instance is created.
await graph.initialize(graphOptions);

주어진 쿼리는 Puppets 그래프의 모든 튜플을 나열해요.

const results = await graph.query(`
SELECT ?s ?p ?o
WHERE {
    GRAPH <Puppets> {
        ?s ?p ?o .
    }
}
ORDER BY ?s`);
console.log(results);
s,p,o
P1,name,Ernie
P1,show,Sesame Street
P1,http://www.w3.org/1999/02/22-rdf-syntax-ns#type,Puppet
P2,name,Bert
P2,show,Sesame Street
P2,http://www.w3.org/1999/02/22-rdf-syntax-ns#type,Puppet

[Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/oss/javascript/integrations/graphs/sap_hana_rdf_graph.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose).

더 알아보기