以编程方式使用文档

有关 SAP HANA 向量存储的设置详情,请参阅指南 向量存储:SAP HANA.

我们在此使用相同的设置:

dotenv.config();


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

为了能够以良好性能进行自查询,我们为向量存储表创建额外的元数据字段 用于 HANA 中的向量存储表:

await new Promise<void>((resolve, reject) => {
  client.exec(
    `DROP TABLE LANGCHAIN_DEMO_SELF_QUERY`,
    (dropErr: Error) => {
      // Ignore drop errors
      client.exec(
        `CREATE TABLE "LANGCHAIN_DEMO_SELF_QUERY"  (
          "name" NVARCHAR(100), "is_active" BOOLEAN, "id" INTEGER, "height" DOUBLE,
          "VEC_TEXT" NCLOB,
          "VEC_META" NCLOB,
          "VEC_VECTOR" REAL_VECTOR
        )`,
        (createErr: Error) => {
          if (createErr) {
            reject(createErr);
          } else {
            resolve();
          }
        }
      );
    }
  );
});

让我们添加一些文档。

const embeddings = new OpenAIEmbeddings();

const db = new HanaDB(embeddings, {
  connection: client,
  tableName: "LANGCHAIN_DEMO_SELF_QUERY",
  specificMetadataColumns: ["name", "is_active", "id", "height"],
});
await db.initialize();

const docs = [
  new Document({
    pageContent: "First",
    metadata: { name: "adam", is_active: true, id: 1, height: 10.0 },
  }),
  new Document({
    pageContent: "Second",
    metadata: { name: "bob", is_active: false, id: 2, height: 5.7 },
  }),
  new Document({
    pageContent: "Third",
    metadata: { name: "jane", is_active: true, id: 3, height: 2.4 },
  }),
];

await db.delete({ filter: {} });
await db.addDocuments(docs);

自查询

现在进入主要部分:以下是如何为 HANA 向量存储构建 SelfQueryRetriever:

const llm = new ChatOpenAI({ model: "gpt-3.5-turbo" });

const metadataFieldInfo: AttributeInfo[] = [
  { name: "name", description: "The name of the person", type: "string" },
  { name: "is_active", description: "Whether the person is active", type: "boolean" },
  { name: "id", description: "The ID of the person", type: "integer" },
  { name: "height", description: "The height of the person", type: "float" },
];

const contentDescription = "A collection of persons";

const hanaTranslator = new HanaTranslator();

const retriever = await SelfQueryRetriever.fromLLM({
  llm,
  vectorStore: db,
  documentContentDescription: contentDescription,
  attributeInfo: metadataFieldInfo,
  structuredQueryTranslator: hanaTranslator,
});

让我们使用此检索器来准备一个(自)查询:

const queryPrompt = "Which person is not active?"
const retrievedDocs = await retriever.invoke(queryPrompt);

for (const doc of retrievedDocs){
  console.log("-".repeat(80));
  console.log(doc.pageContent + " " + JSON.stringify(doc.metadata));
}
--------------------------------------------------------------------------------
Second {"name":"bob","is_active":false,"id":2,"height":5.7}