`HanaSparqlQAChain`을 이용한 질의응답

HanaSparqlQAChain을 이용한 질의응답 (Question Answering with HanaSparqlQAChain)

설정 및 설치

이 기능을 사용하려면 @sap/hana-langchain 패키지와 피어 의존성을 설치하세요:

npm install @sap/hana-langchain @langchain/core@latest @langchain/classic@latest langchain@latest

SAP HANA Cloud 인스턴스에 대한 연결을 만듭니다.

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();
    }
  });
});

HanaSparqlQAChain은 다음을 하나로 묶습니다:

  1. 스키마 인지형 SPARQL 생성
  2. SAP HANA에 대한 쿼리 실행
  3. 자연어 답변 포맷팅

초기화

  • 쿼리를 생성하고 해석할 LLM
  • (연결, graph_uri, 온톨로지를 갖춘) HanaRdfGraph

HanaRdfGraph 인스턴스 만드는 방법에 대해 자세히 알아보려면 HanaRdfGraph의 단계를 따르세요.

HanaSparqlQAChain을 임포트합니다.

import { HanaSparqlQAChain } from "@sap/hana-langchain";
const qaChain = HanaSparqlQAChain.fromLLM({ llm, graph, allowDangerousRequests: true, verbose: true });

파이프라인 개요

  1. SPARQL 생성
    • SPARQL 생성 프롬프트를 사용합니다.
    • 입력: schema (graph.getSchema()의 Turtle), prompt (사용자 질문)
  2. 쿼리 후처리
    • 모델 출력에서 SPARQL 추출
    • 누락된 경우 FROM <graph_uri> 주입
    • 공통 접두사(rdf:, rdfs:, owl:, xsd:) 보장
  3. 실행
    • graph.query(generatedSparql)
  4. 답변 작성
    • 입력이 context(결과), prompt(원래 질문)인 QA 프롬프트를 사용합니다.

프롬프트 템플릿

"SPARQL 생성" 프롬프트

sparqlGenerationPrompt는 LLM이 사용자 질문과 제공된 스키마로 SPARQL 쿼리를 생성하도록 안내하는 데 사용됩니다.

답변 프롬프트

qaPrompt는 LLM이 데이터베이스 결과만을 근거로 자연어 답변을 만들도록 지시합니다. 기본 프롬프트는 여기에서 찾을 수 있습니다: prompts.ts

프롬프트 커스터마이징

초기화 시 기본값을 재정의할 수 있습니다:

const qaChain = HanaSparqlQAChain.fromLLM({
  llm,
  graph,
  allowDangerousRequests: true,
  verbose: true,
  sparqlGenerationPrompt: YOUR_SPARQL_PROMPT,
  qaPrompt: YOUR_QA_PROMPT,
});
  • sparql_generation_prompt는 입력 변수 ["schema", "prompt"]를 가져야 합니다.
  • qa_prompt는 입력 변수 ["context", "prompt"]를 가져야 합니다.

예시: "Movies" 지식 그래프에 대한 질의응답

전제 조건: triple store 기능이 활성화된 SAP HANA Cloud 인스턴스가 있어야 합니다. 자세한 지침은 Triple Store 활성화를 참조하세요.
kgdocu_movies 예시 데이터를 로드하세요. Knowledge Graph 예시를 참조하세요.

아래에서 우리는:

  1. "movies" 데이터 그래프를 가리키는 HanaRdfGraph를 인스턴스화하고
  2. LLM이 지원하는 HanaSparqlQAChain으로 감싼 뒤
  3. 자연어 질문을 하고 체인의 응답을 출력합니다.

이것은 LLM이 내부적으로 SPARQL을 생성하고, SAP HANA에 실행하며, 사람이 읽을 수 있는 답변을 반환하는 방법을 보여 줍니다.

먼저 SAP HANA Cloud 인스턴스에 대한 연결을 만듭니다.

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();
    }
  });
});

그런 다음 지식 그래프 인스턴스를 설정합니다.

import { HanaRdfGraph, HanaRdfGraphOptions } from "@sap/hana-langchain";

const graphOptions: HanaRdfGraphOptions = {
  connection: client,
  graphUri: "kgdocu_movies",
  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);
// Serialise the graph schema (optional)
// Internally, the schema is stored as an N3 Store instance,
// We use the N3 Writer to serialise it to Turtle format for display.
const schemaStore = graph.getSchema();
const writer = new Writer({
  prefixes: {
    rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
    rdfs: "http://www.w3.org/2000/01/rdf-schema#",
    owl: "http://www.w3.org/2002/07/owl#",
    xsd: "http://www.w3.org/2001/XMLSchema#",
  },
});
schemaStore.forEach((quad) => {
  writer.addQuad(quad);
});
writer.end((error, result) => {
  if (error) {
    console.error("Error serialising schema:", error);
  } else {
    console.log("Graph Schema in Turtle format:\n", result);
  }
});
Graph Schema in Turtle format:
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix owl: <http://www.w3.org/2002/07/owl#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
...

그런 다음 LLM을 초기화합니다.

import { ChatOpenAI } from "@langchain/openai"; // or your chosen LLM
const llm = new ChatOpenAI({ model: "gpt-4o" });

그 후 SPARQL QA Chain을 만듭니다.

import { HanaSparqlQAChain, HanaSparqlQAChainOptions } from "@sap/hana-langchain";

const chainOptions: HanaSparqlQAChainOptions = {
  llm,
  allowDangerousRequests: true,
  graph,
  debug: true,
};

const query = "which actors acted in Blade Runner?";
// const query = "Which movies are in the data?"
// const query = "In which movies did Keanu Reeves and Carrie-Anne Moss play in together"
// const query = "which movie genres are in the data?"
// const query = "which are the two most assigned movie genres?"
// const query = "where were the actors of 'Blade Runner' born?"
// const query = "which actors acted together in a movie and were born in the same city?"

const response = await chain.invoke({ query });
console.log(response["result"]);
Generated SPARQL:
```sparql
PREFIX kg: <http://kg.demo.sap.com/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?actor ?actorLabel
WHERE {
    ?movie rdf:type kg:Film .
    ?movie kg:title "Blade Runner" .
    ?actor kg:acted_in ?movie .
    ?actor rdfs:label ?actorLabel .
}

Final SPARQL:

PREFIX kg: http://kg.demo.sap.com/ PREFIX rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns# PREFIX rdfs: http://www.w3.org/2000/01/rdf-schema# SELECT ?actor ?actorLabel

  FROM <kgdocu_movies>
  WHERE {
?movie rdf:type kg:Film .
?movie kg:title "Blade Runner" .
?actor kg:acted_in ?movie .
?actor rdfs:label ?actorLabel .

}

Full Context: actor,actorLabel http://www.wikidata.org/entity/Q1353691,Morgan Paull ... The actors who acted in Blade Runner include Morgan Paull, William Sanderson, James Hong, Brion James, M. Emmet Walsh, Joe Turkel, Daryl Hannah, Joanna Cassidy, Rutger Hauer, Hy Pyke, Sean Young, and Edward James Olmos.


## 내부에서 무슨 일이 일어나나요?

1. **SPARQL 생성**
   체인은 Turtle 형식으로 된 온톨로지(`graph.getSchema()`)와 사용자 질문을 `SPARQL_GENERATION_SELECT_PROMPT`와 함께 LLM에 전달합니다. 그러면 LLM은 스키마에 맞춘 유효한 `SELECT` 쿼리를 생성합니다.
2. **전처리 및 실행**
   * **추출 및 정리**: LLM 응답에서 원시 SPARQL 텍스트를 가져옵니다.
   * **그래프 컨텍스트 주입**: 누락된 경우 `FROM <graph_uri>`를 추가하고 공통 접두사(`rdf:`, `rdfs:`, `owl:`, `xsd:`)가 선언되도록 합니다.
   * **HANA에서 실행**: `HanaRdfGraph.query()`로 명명된 그래프에 최종 쿼리를 실행합니다.
3. **답변 작성**
   반환된 CSV(또는 Turtle) 결과가 다시 LLM에 전달됩니다 — 이번에는 `SPARQL_QA_PROMPT`와 함께. LLM은 검색된 데이터에만 엄격히 기반하여, 환각 없이 간결하고 사람이 읽을 수 있는 답변을 생성합니다.

## 더 알아보기

* [HanaRdfGraph](/oss/javascript/integrations/graphs/sap_hana_rdf_graph)

> 출처: [문서](https://docs.langchain.com/oss/javascript/integrations/chains/sap_hana_sparql_qa_chain)