Conocimiento y búsqueda vectorial
Ingesta documentos, arma colecciones de conocimiento y consúltalas por significado.
Descripción general
Conocimiento y búsqueda vectorial mantiene el conocimiento de tu organización donde una aplicación puede hacerle preguntas por significado. Tiene tres partes, todas en https://ai.inovacc.dev:
- la Vector Database (base de datos vectorial): un almacén administrado de pasajes de texto que ingestas y buscas, con filtros, ámbitos y reordenamiento opcional;
- las colecciones de conocimiento: envía un lote de archivos mixtos (documentos, imágenes, video) y haz que se procesen en paquetes de conocimiento; luego descarga el resultado, consúltalo, chatea con él con citas, o haz que se redacte un informe sobre él;
- los trabajos de conocimiento: convierten una grabación larga en una base de conocimiento que descargas como un solo archivo comprimido.
El problema que resuelve es todo lo que hay entre "tenemos archivos" y "el asistente puede responder a partir de ellos": extraer texto, cortarlo en pasajes, generar embeddings, indexar, mantener el índice consistente y citar la fuente de cada respuesta. Inovacc hace esos pasos y tú llamas a un puñado de endpoints.
Úsalo cuando las respuestas deban salir de tu propio material. Si ya ejecutas tu propio índice vectorial, los Embeddings de IA te dan solo los vectores. Cuando la respuesta es texto libre sin fuentes, usa el Chat con IA. Inovacc habilita cada parte para tu organización; una parte que no está habilitada responde 403 (vector_database_disabled, collections_disabled o knowledge_disabled).
Conceptos
Vector Database y su perfil. Tu organización crea una base de datos con POST /v1/vector/databases, eligiendo un perfil de embeddings de GET /v1/vector/profiles. Un perfil indica la modalidad (text), los idiomas (english o multilingual), las dimensiones y la métrica de distancia; los ids se ven como text-multilingual-1024. Eliges un perfil, nunca un modelo. El perfil no puede cambiar: para usar otro, elimina la base de datos, crea una nueva e ingesta de nuevo.
Documentos, ámbitos y modos. Ingestas pasajes con tu propio id, su text y metadata plana opcional. Un pasaje va a un ámbito: shared (todos los servicios del espacio de trabajo de tu organización) o local (solo la clave de API que lo escribió). Las consultas toman un modo: shared, local, o hybrid para buscar en ambos y combinar por puntuación. Se puede filtrar por seis claves de metadatos: kind, source, category, tag, language, created_at. Los fragmentos que comparten un document_id forman un documento con una generation (tu número de versión), lo que permite eliminar o reemplazar un documento completo de una vez.
Colecciones y su modo. Una colección se crea en uno de tres modos, fijos durante toda su vida: download (procesa archivos, descarga los paquetes y luego no queda nada), cloud (Inovacc conserva el contenido procesado y sus vectores para que puedas ejecutar query, chat y un analysis) o local_vectors (Inovacc conserva solo vectores, nunca texto: tú haces embed de tus propios fragmentos y query devuelve ids de fragmentos y puntuaciones). Las colecciones se conservan 30 días por defecto; una organización configurada en retención zero las tiene eliminadas una hora después de que empieza la descarga.
Elementos. Un archivo se une a una colección en la solicitud (hasta 16 MiB), desde una carga completada (video de más de 16 MiB), por URL pública, o por una URL firmada sellada a una clave de un solo uso para que nunca se almacene. Cada elemento pasa por queued, processing, y luego done o failed; un elemento fallido no detiene a los demás.
Consistencia eventual y searchable. El índice vectorial aplica las escrituras de forma asíncrona: un vector se puede leer unos segundos, a veces minutos, después de haberse escrito. GET /v1/vector/databases y toda respuesta de colección reportan searchable; una consulta enviada mientras es false puede omitir los pasajes más recientes. El indexing.complete de una colección cloud es true solo cuando cada fragmento está escrito y se puede leer.
Trabajos, potencia y presupuesto. Un trabajo de conocimiento toma una carga completada de una grabación, una transcripción y notas opcionales, un power (light, medium o max) y un max_price_usd obligatorio. Un trabajo que supera el tope de tu organización se rechaza antes de cualquier trabajo de pago.
Cómo funciona
Toda llamada lleva Authorization: Bearer <key>. Tu organización se obtiene de la clave. X-Operation-Id es obligatorio en las llamadas POST de colecciones, cargas y trabajos y las hace idempotentes: un reintento con el mismo id devuelve la primera respuesta (X-Idempotent-Replay: true) y no agrega nada; el mismo id con un archivo distinto es 409 operation_id_reused. En la Vector Database es opcional, porque la ingesta y la eliminación son idempotentes por construcción: ingestar un id existente lo reemplaza.
Una consulta (POST /v1/vector/query) toma mode, query (de 1 a 8,000 caracteres), top_k (de 1 a 50) y un filter opcional; devuelve las coincidencias de mejor a peor, cada una con id, score, text y metadata. Con "retrieval": "vector_rerank" y un rerank_profile, una lista de candidatos más amplia es reordenada por una etapa de reordenamiento; el objeto retrieval de la respuesta indica si el reordenamiento se aplicó o si se recurrió al orden vectorial.
Una colección funciona en pasos que puedes observar: créala, agrega elementos (202, queued), léela hasta que status sea complete, y luego descarga, consulta o chatea. Leer una colección cloud también avanza su indexación, una cantidad acotada por llamada, y cada respuesta lleva el progreso de indexing. chat responde solo a partir de las fuentes recuperadas, numera cada cita con el elemento, el paquete, el fragmento y el localizador, y dice que no puede responder cuando las fuentes no cubren la pregunta. Un analysis se construye a lo largo de varias solicitudes: repite POST o GET cada pocos segundos hasta que responda 200 con el informe.
Un trabajo es asíncrono: POST /v1/knowledge/jobs responde 202 con job_id, status_url y poll_after_seconds (también como Retry-After). Lee el estado cuando se te indique; la plataforma pronostica el tiempo hasta terminar e incluye eta_seconds mientras puede. Cuando state es done, descarga el archivo comprimido; se conserva 24 horas.
Lo que se mide: tokens de embeddings y vectores escritos por ingesta e indexación, consultas, reordenamientos como su propia unidad, llamadas de chat en tu ruta de chat, y trabajos por su precio. POST /v1/knowledge/estimates calcula el precio de una grabación antes de que la cargues, sin costo.
Primeros pasos
Necesitas una clave de API y la parte que quieras habilitada para tu organización (Autenticación).
- Crea la base de datos.
GET /v1/vector/profiles, elige un perfil y luegoPOST /v1/vector/databasescon{"profile":"<id>"}. La respuesta es 201 con la base de datos. - Ingesta pasajes.
POST /v1/vector/ingestcon"scope":"shared"y dos o tres documentos (consulta los ejemplos). La respuesta indica cuántos seingestedy lista losskippedcon un motivo. - Espera a
searchable.GET /v1/vector/databaseshasta quesearchableseatrue. - Consulta.
POST /v1/vector/querycon"mode":"shared"y una pregunta redactada de forma distinta a tus pasajes. El pasaje más cercano aparece primero, con suscore. - Prueba una colección.
POST /v1/collectionscon{"mode":"cloud"}, agrega un PDF a/items, lee la colección hasta queindexing.completeseatrue, y luegoPOST /v1/collections/{id}/chaty revisa lascitations.
Casos de uso
Un asistente basado en tu manual. Tu intranet ingesta cada página de políticas como fragmentos bajo su document_id, con metadatos de category. El asistente consulta con un filtro de category y pasa los mejores pasajes a su propio prompt. Cuando una página cambia, se ingesta de nuevo con una generation mayor, y los fragmentos que la nueva versión ya no tiene dejan de aparecer de inmediato.
Preguntas sobre los archivos entregados por un cliente. Un consultor crea una colección cloud por proyecto, agrega los contratos y las hojas de cálculo que envió el cliente, y hace preguntas mediante chat. Cada respuesta cita el elemento y la página en que se apoya, de modo que cada afirmación se puede verificar antes de pasar a un informe; analysis produce un resumen, entidades y contradicciones entre los archivos.
De grabaciones de reuniones a una base de conocimiento. Después de cada reunión grabada, la aplicación estima el precio, carga el video en partes de 64 MiB con la propia transcripción de la llamada como referencia, e inicia un trabajo con max_price_usd. Cuando el trabajo está done, el archivo comprimido (audio, fotogramas clave y la base de conocimiento) se archiva junto con la reunión.
Límites y precios
| Límite | Valor |
|---|---|
| Cuerpo de solicitud de la Vector Database | 1 MiB |
| Documentos por ingesta, ids por eliminación | 100 |
Un documento (id + text + metadata) | 10 KiB |
Texto de consulta; top_k | 8,000 caracteres; 50 |
Valores de $in en un filtro | 20 |
| Elemento en el cuerpo de una solicitud, u obtenido por URL | 16 MiB |
| Elementos por colección | 100; 1 GiB de archivos enviados en solicitudes; 20 GiB de video por carga |
top_k de consulta de colección; mensajes de chat | 20; de 1 a 20 mensajes de hasta 8,000 caracteres |
Fragmentos por llamada embed | 100, cada uno de hasta 8,000 caracteres |
| Llamadas al modelo de análisis por informe | 32 |
| Tamaño de las partes de una carga | 64 MiB (todas las partes menos la última) |
| Carga que no es video (transcripción, notas) | 16 MiB |
| Carga de grabación | el tope de tu organización |
| Claves de obtención sin usar | 16, cada una válida una vez durante 60 segundos |
| Resultado del trabajo conservado | 24 horas |
| Retención de colecciones | 30 días por defecto |
Precios: a consultar. Una grabación procesada por un trabajo se cobra en minutos de video, y POST /v1/knowledge/estimates devuelve su precio línea por línea antes de que cargues cualquier cosa. El chat sobre una colección se mide como el Chat con IA en tu ruta de chat.
Errores
| Estado | Código | Qué significa y qué hacer |
|---|---|---|
| 400 | invalid_body, unsupported_field | Un campo o valor que la ruta no acepta; revisa los campos de la ruta. |
| 400 | invalid_profile | Elige un perfil listado por GET /v1/vector/profiles. |
| 400 | confirmation_required | Eliminar la base de datos requiere {"confirm":"delete-database-and-all-vectors"}. |
| 400 | invalid_url, signed_url_must_be_sealed | Solo URL https públicas en el puerto 443; una URL firmada debe estar sellada. |
| 400 | fetch_key_invalid, invalid_sealed_url | Solicita una nueva clave de obtención y sella de nuevo. |
| 403 | vector_database_disabled, collections_disabled, knowledge_disabled | Esa parte no está habilitada para tu organización. |
| 403 | budget_exceeded | El max_price_usd del trabajo supera el tope de tu organización. |
| 404 | collection_not_found, job_not_found, upload_not_found, analysis_not_found | Revisa el id; la descarga de un trabajo también es 404 hasta que está done. |
| 409 | vector_database_not_created, vector_database_exists, vector_database_deleting | Crea primero la base de datos; una por organización; espera a que termine una eliminación. |
| 409 | mode_not_supported | La operación no existe en el modo de esta colección. |
| 409 | collection_incomplete, collection_full | Espera a que terminen los elementos; la colección está en su límite. |
| 409 | upload_incomplete, operation_id_reused, operation_in_progress | Termina la carga; usa un nuevo id de operación para un archivo distinto; espera. |
| 410 | collection_expired, result_expired | La retención terminó; procesa de nuevo. |
| 413 | request_too_large, url_too_large | Usa POST /v1/uploads para archivos grandes. |
| 415, 422 | unsupported_media_type, input_rejected, archive_rejected | El tipo de archivo no se lee, o el archivo fue rechazado (reason indica por qué). |
| 429 | too_many_fetch_keys y los códigos de cuota | Usa o deja vencer las claves que tienes; consulta Errores. |
| 502, 504 | url_fetch_failed, url_fetch_timeout, upstream_error, timeout_error | Falló la URL o el procesamiento; reintenta. |
| 503 | service_unavailable | Reintenta más tarde; no se adivinó nada. |
Buenas prácticas
- Agrupa los fragmentos bajo un
document_idy aumentagenerationcuando cambie la fuente; la eliminación y el reemplazo funcionan entonces por documento. - Envía
content_sha256con cada fragmento y compáralo conGET /v1/vector/documentspara resincronizar tu copia sin volver a ingestar todo. - Revisa
searchable(oindexing.complete) antes de confiar en los pasajes más recientes. - Mantén la respuesta de un pasaje dentro de sus primeros 2,000 caracteres cuando uses reordenamiento; el reordenador solo lee esa cantidad.
- Compara
vector_rerankconvectorsimple en tus propios datos, sobre todo fuera del inglés, antes de depender de él. - Estima siempre antes de un trabajo y configura
max_price_usd; consulta el estado enpoll_after_seconds, no más rápido. - Sella las URL firmadas; nunca envíes una URL que lleve un inicio de sesión. Carga los bytes en su lugar.
- Revisa las citas: un modelo puede citar una fuente real para algo que esa fuente no dice.
Relacionados
- Embeddings de IA, Chat con IA
- Archivos: almacena los archivos fuente en sí
- Autenticación, Errores, Límites
Autenticación
Toda llamada lleva tu clave; tu organización viene de ella. Consulta la guía de autenticación.
AuthorizationX-Operation-IdEndpoints
POST /v1/vector/ingest
POST /v1/vector/query
POST /v1/collections
POST /v1/collections/{id}/query
POST /v1/knowledge/jobs
Ejemplo
Lenguaje
⋮
cURL
curl -X POST "https://ai.inovacc.dev/v1/vector/ingest" \
-H "Authorization: Bearer $INOVACC_API_KEY" \
-H "X-Operation-Id: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
}'curl -X POST "https://ai.inovacc.dev/v1/vector/ingest" \
-H "Authorization: Bearer $INOVACC_API_KEY" \
-H "X-Operation-Id: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
}'
TypeScript
import crypto from "node:crypto";
const body: Record<string, unknown> = {
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
};
const url = "https://ai.inovacc.dev/v1/vector/ingest";
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
"X-Operation-Id": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(response.status, await response.text());import crypto from "node:crypto";
const body: Record<string, unknown> = {
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
};
const url = "https://ai.inovacc.dev/v1/vector/ingest";
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
"X-Operation-Id": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(response.status, await response.text());
Python
import json
import os
import urllib.request
import uuid
body = {
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr",
},
"document_id": "handbook-leave",
"generation": 1,
},
],
}
request = urllib.request.Request(
"https://ai.inovacc.dev/v1/vector/ingest",
data=json.dumps(body).encode(),
method="POST",
headers={
"User-Agent": "inovacc-python-sample",
"Authorization": "Bearer " + os.environ["INOVACC_API_KEY"],
"X-Operation-Id": str(uuid.uuid4()),
"Content-Type": "application/json",
},
)
with urllib.request.urlopen(request) as response:
print(response.status, response.read().decode())import json
import os
import urllib.request
import uuid
body = {
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr",
},
"document_id": "handbook-leave",
"generation": 1,
},
],
}
request = urllib.request.Request(
"https://ai.inovacc.dev/v1/vector/ingest",
data=json.dumps(body).encode(),
method="POST",
headers={
"User-Agent": "inovacc-python-sample",
"Authorization": "Bearer " + os.environ["INOVACC_API_KEY"],
"X-Operation-Id": str(uuid.uuid4()),
"Content-Type": "application/json",
},
)
with urllib.request.urlopen(request) as response:
print(response.status, response.read().decode())
Go
package main
import (
"crypto/rand"
"fmt"
"io"
"net/http"
"os"
"strings"
)
const url = "https://ai.inovacc.dev/v1/vector/ingest"
const body = `{
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
}`
// newUUID returns a random (version 4) UUID, from the standard library alone.
func newUUID() string {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
panic(err)
}
b[6] = b[6]&0x0f | 0x40
b[8] = b[8]&0x3f | 0x80
return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
}
func main() {
req, err := http.NewRequest("POST", url, strings.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("INOVACC_API_KEY"))
req.Header.Set("X-Operation-Id", newUUID())
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
fmt.Println(res.Status, string(out))
}package main
import (
"crypto/rand"
"fmt"
"io"
"net/http"
"os"
"strings"
)
const url = "https://ai.inovacc.dev/v1/vector/ingest"
const body = `{
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
}`
// newUUID returns a random (version 4) UUID, from the standard library alone.
func newUUID() string {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
panic(err)
}
b[6] = b[6]&0x0f | 0x40
b[8] = b[8]&0x3f | 0x80
return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
}
func main() {
req, err := http.NewRequest("POST", url, strings.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("INOVACC_API_KEY"))
req.Header.Set("X-Operation-Id", newUUID())
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
fmt.Println(res.Status, string(out))
}
Rust
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }
// Cargo.toml: serde_json = "1"
// Cargo.toml: uuid = { version = "1", features = ["v4"] }
fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = std::env::var("INOVACC_API_KEY")?;
let body = serde_json::json!({
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
});
let response = reqwest::blocking::Client::new()
.post("https://ai.inovacc.dev/v1/vector/ingest")
.bearer_auth(api_key)
.header("X-Operation-Id", uuid::Uuid::new_v4().to_string())
.json(&body)
.send()?;
println!("{} {}", response.status(), response.text()?);
Ok(())
}// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }
// Cargo.toml: serde_json = "1"
// Cargo.toml: uuid = { version = "1", features = ["v4"] }
fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = std::env::var("INOVACC_API_KEY")?;
let body = serde_json::json!({
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
});
let response = reqwest::blocking::Client::new()
.post("https://ai.inovacc.dev/v1/vector/ingest")
.bearer_auth(api_key)
.header("X-Operation-Id", uuid::Uuid::new_v4().to_string())
.json(&body)
.send()?;
println!("{} {}", response.status(), response.text()?);
Ok(())
}
JavaScript
import crypto from "node:crypto";
const body = {
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
};
const url = "https://ai.inovacc.dev/v1/vector/ingest";
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
"X-Operation-Id": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(response.status, await response.text());import crypto from "node:crypto";
const body = {
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
};
const url = "https://ai.inovacc.dev/v1/vector/ingest";
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
"X-Operation-Id": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(response.status, await response.text());
PHP
<?php
$body = <<<'JSON'
{
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
}
JSON;
function uuid4(): string
{
$bytes = random_bytes(16);
$bytes[6] = chr(ord($bytes[6]) & 0x0f | 0x40);
$bytes[8] = chr(ord($bytes[8]) & 0x3f | 0x80);
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($bytes), 4));
}
$curl = curl_init('https://ai.inovacc.dev/v1/vector/ingest');
curl_setopt_array($curl, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('INOVACC_API_KEY'),
'X-Operation-Id: ' . uuid4(),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($curl);
echo curl_getinfo($curl, CURLINFO_HTTP_CODE), ' ', $response, "\n";
curl_close($curl);<?php
$body = <<<'JSON'
{
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
}
JSON;
function uuid4(): string
{
$bytes = random_bytes(16);
$bytes[6] = chr(ord($bytes[6]) & 0x0f | 0x40);
$bytes[8] = chr(ord($bytes[8]) & 0x3f | 0x80);
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($bytes), 4));
}
$curl = curl_init('https://ai.inovacc.dev/v1/vector/ingest');
curl_setopt_array($curl, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('INOVACC_API_KEY'),
'X-Operation-Id: ' . uuid4(),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($curl);
echo curl_getinfo($curl, CURLINFO_HTTP_CODE), ' ', $response, "\n";
curl_close($curl);
Ruby
require "net/http"
require "securerandom"
require "uri"
uri = URI('https://ai.inovacc.dev/v1/vector/ingest')
body = <<~'JSON'
{
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
}
JSON
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('INOVACC_API_KEY')}"
request["X-Operation-Id"] = SecureRandom.uuid
request["Content-Type"] = "application/json"
request.body = body
response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
puts "#{response.code} #{response.body}"require "net/http"
require "securerandom"
require "uri"
uri = URI('https://ai.inovacc.dev/v1/vector/ingest')
body = <<~'JSON'
{
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
}
JSON
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('INOVACC_API_KEY')}"
request["X-Operation-Id"] = SecureRandom.uuid
request["Content-Type"] = "application/json"
request.body = body
response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
puts "#{response.code} #{response.body}"
Java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;
public class Main {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("INOVACC_API_KEY");
String body = "{" +
"\"scope\": \"shared\"," +
"\"documents\": [" +
"{" +
"\"id\": \"handbook-leave-1\"," +
"\"text\": \"Employees accrue two and a half days of paid leave per month.\"," +
"\"metadata\": {" +
"\"category\": \"hr\"" +
"}," +
"\"document_id\": \"handbook-leave\"," +
"\"generation\": 1" +
"}" +
"]" +
"}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://ai.inovacc.dev/v1/vector/ingest"))
.header("Authorization", "Bearer " + apiKey)
.header("X-Operation-Id", UUID.randomUUID().toString())
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;
public class Main {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("INOVACC_API_KEY");
String body = "{" +
"\"scope\": \"shared\"," +
"\"documents\": [" +
"{" +
"\"id\": \"handbook-leave-1\"," +
"\"text\": \"Employees accrue two and a half days of paid leave per month.\"," +
"\"metadata\": {" +
"\"category\": \"hr\"" +
"}," +
"\"document_id\": \"handbook-leave\"," +
"\"generation\": 1" +
"}" +
"]" +
"}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://ai.inovacc.dev/v1/vector/ingest"))
.header("Authorization", "Bearer " + apiKey)
.header("X-Operation-Id", UUID.randomUUID().toString())
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}
C#
using System.Text;
var body = "{" +
"\"scope\": \"shared\"," +
"\"documents\": [" +
"{" +
"\"id\": \"handbook-leave-1\"," +
"\"text\": \"Employees accrue two and a half days of paid leave per month.\"," +
"\"metadata\": {" +
"\"category\": \"hr\"" +
"}," +
"\"document_id\": \"handbook-leave\"," +
"\"generation\": 1" +
"}" +
"]" +
"}";
var url = "https://ai.inovacc.dev/v1/vector/ingest";
var apiKey = Environment.GetEnvironmentVariable("INOVACC_API_KEY");
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Add("Authorization", $"Bearer {apiKey}");
request.Headers.Add("X-Operation-Id", Guid.NewGuid().ToString());
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
using var response = await client.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");using System.Text;
var body = "{" +
"\"scope\": \"shared\"," +
"\"documents\": [" +
"{" +
"\"id\": \"handbook-leave-1\"," +
"\"text\": \"Employees accrue two and a half days of paid leave per month.\"," +
"\"metadata\": {" +
"\"category\": \"hr\"" +
"}," +
"\"document_id\": \"handbook-leave\"," +
"\"generation\": 1" +
"}" +
"]" +
"}";
var url = "https://ai.inovacc.dev/v1/vector/ingest";
var apiKey = Environment.GetEnvironmentVariable("INOVACC_API_KEY");
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Add("Authorization", $"Bearer {apiKey}");
request.Headers.Add("X-Operation-Id", Guid.NewGuid().ToString());
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
using var response = await client.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
Kotlin
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.util.UUID
fun main() {
val apiKey = System.getenv("INOVACC_API_KEY")
val body = "{" +
"\"scope\": \"shared\"," +
"\"documents\": [" +
"{" +
"\"id\": \"handbook-leave-1\"," +
"\"text\": \"Employees accrue two and a half days of paid leave per month.\"," +
"\"metadata\": {" +
"\"category\": \"hr\"" +
"}," +
"\"document_id\": \"handbook-leave\"," +
"\"generation\": 1" +
"}" +
"]" +
"}"
val request = HttpRequest.newBuilder()
.uri(URI.create("https://ai.inovacc.dev/v1/vector/ingest"))
.header("Authorization", "Bearer " + apiKey)
.header("X-Operation-Id", UUID.randomUUID().toString())
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(body))
.build()
val response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString())
println("${response.statusCode()} ${response.body()}")
}import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.util.UUID
fun main() {
val apiKey = System.getenv("INOVACC_API_KEY")
val body = "{" +
"\"scope\": \"shared\"," +
"\"documents\": [" +
"{" +
"\"id\": \"handbook-leave-1\"," +
"\"text\": \"Employees accrue two and a half days of paid leave per month.\"," +
"\"metadata\": {" +
"\"category\": \"hr\"" +
"}," +
"\"document_id\": \"handbook-leave\"," +
"\"generation\": 1" +
"}" +
"]" +
"}"
val request = HttpRequest.newBuilder()
.uri(URI.create("https://ai.inovacc.dev/v1/vector/ingest"))
.header("Authorization", "Bearer " + apiKey)
.header("X-Operation-Id", UUID.randomUUID().toString())
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(body))
.build()
val response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString())
println("${response.statusCode()} ${response.body()}")
}
Swift
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
let body = #"""
{
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
}
"""#
let apiKey = ProcessInfo.processInfo.environment["INOVACC_API_KEY"] ?? ""
let url = URL(string: "https://ai.inovacc.dev/v1/vector/ingest")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue(UUID().uuidString, forHTTPHeaderField: "X-Operation-Id")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = Data(body.utf8)
let (data, response) = try await URLSession.shared.data(for: request)
let status = (response as? HTTPURLResponse)?.statusCode ?? 0
print(status, String(decoding: data, as: UTF8.self))import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
let body = #"""
{
"scope": "shared",
"documents": [
{
"id": "handbook-leave-1",
"text": "Employees accrue two and a half days of paid leave per month.",
"metadata": {
"category": "hr"
},
"document_id": "handbook-leave",
"generation": 1
}
]
}
"""#
let apiKey = ProcessInfo.processInfo.environment["INOVACC_API_KEY"] ?? ""
let url = URL(string: "https://ai.inovacc.dev/v1/vector/ingest")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue(UUID().uuidString, forHTTPHeaderField: "X-Operation-Id")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = Data(body.utf8)
let (data, response) = try await URLSession.shared.data(for: request)
let status = (response as? HTTPURLResponse)?.statusCode ?? 0
print(status, String(decoding: data, as: UTF8.self))
Detalles de la fuente
- Id
- identity/component-taxonomy/capabilities#knowledge
- Repositorio
- identity
- Ruta
- contracts/component-taxonomy/catalog/capabilities.json
- Commit
- 08ef3cd75d82
- Id
- identity/component-taxonomy/quickstart#knowledge
- Repositorio
- identity
- Ruta
- contracts/component-taxonomy/catalog/capabilities.json
- Commit
- 08ef3cd75d82