š§ 1. Introdução
A integração entre .NET 10 e Pinecone permite desenvolver aplicações capazes de armazenar, pesquisar e recuperar informações por similaridade semântica.
Essa abordagem Ć© especialmente Ćŗtil em projetos de:
- InteligĆŖncia Artificial (IA).
- RAG (Retrieval-Augmented Generation).
- Assistentes virtuais e chatbots.
- Busca semântica de documentos.
- Sistemas de recomendação.
- Recuperação inteligente de conhecimento.
- AplicaƧƵes baseadas em LLMs (Large Language Models).
Diferentemente dos bancos relacionais tradicionais, que normalmente consultam dados por condiƧƵes e valores exatos, o Pinecone foi projetado para trabalhar com vetores (embeddings).
Esses vetores representam o significado de textos, documentos e outros conteúdos em um espaço matemÔtico. Dessa forma, conseguimos encontrar informações relacionadas pelo contexto, mesmo quando as palavras utilizadas são diferentes.
Neste artigo, vamos implementar uma integração utilizando:
- .NET 10 e C#.
- Pinecone Vector Database.
- API REST do Pinecone.
- HttpClient e IHttpClientFactory.
- Injeção de dependência.
- Arquitetura organizada em camadas.
- Operações de inserção e pesquisa vetorial.
š§ 2. O que Ć© Pinecone?
O Pinecone Ć© um banco de dados vetorial gerenciado, desenvolvido para armazenar e consultar embeddings em larga escala.
Seu principal objetivo Ʃ permitir pesquisas por similaridade entre vetores, oferecendo uma infraestrutura especializada para aplicaƧƵes de IA.
Como funciona?
Imagine uma aplicação que armazena documentos sobre desenvolvimento de software.
Podemos cadastrar os seguintes conteĆŗdos:
- Documento 1: Como implementar autenticação JWT com .NET.
- Documento 2: Como proteger endpoints de uma API.
- Documento 3: Como configurar um banco de dados SQL Server.
- Documento 4: Como implementar autorização baseada em polĆticas.
Quando um usuƔrio pesquisa:
"Como proteger uma API desenvolvida em C#?"
Uma busca tradicional pode depender da correspondĆŖncia exata das palavras.
JĆ” uma busca vetorial pode encontrar documentos semanticamente relacionados, como o documento sobre autenticação JWT ou autorização baseada em polĆticas.
Principais conceitos
| Conceito | Descrição |
|---|---|
| Vector | Representação numérica de um conteúdo |
| Embedding | Processo de transformar conteĆŗdo em vetor |
| Index | Estrutura onde os vetores são armazenados |
| Namespace | Divisão lógica dos registros |
| Metadata | InformaƧƵes adicionais associadas ao vetor |
| Similarity Search | Pesquisa por proximidade entre vetores |
| Upsert | Inserção ou atualização de vetores |
| Query | Consulta por similaridade |
š 3. Arquitetura de funcionamento
Uma integração com Pinecone normalmente envolve três etapas principais:
- Transformar o conteĆŗdo em embeddings.
- Armazenar os embeddings no Pinecone.
- Gerar um embedding para a pesquisa e consultar os vetores mais próximos.
Ć importante entender que Pinecone e o modelo de embeddings possuem responsabilidades diferentes.
O Pinecone armazena e pesquisa vetores. O modelo de embeddings transforma textos em representaƧƵes numƩricas.
Fluxo de inserção
flowchart TD
A["Aplicação .NET 10"] --> B["Documento / Texto"]
B --> C["Modelo de Embeddings"]
C --> D["Vetor NumƩrico"]
D --> E["Pinecone API"]
E --> F["Vector Index"]
F --> G["Armazenamento"]
Fluxo de pesquisa
flowchart TD
A["UsuƔrio realiza uma pesquisa"] --> B["API .NET 10"]
B --> C["Modelo de Embeddings"]
C --> D["Vetor da consulta"]
D --> E["Pinecone Query"]
E --> F["Pesquisa por similaridade"]
F --> G["Documentos relacionados"]
G --> H["Resposta para a aplicação"]
Em aplicaƧƵes RAG, os documentos recuperados podem ser enviados posteriormente para um LLM, que utiliza esse contexto para construir uma resposta.
šļø 4. Criando o projeto .NET 10
Vamos comeƧar criando uma Web API.
dotnet new webapi -n PineconeIntegration
cd PineconeIntegration
Para este exemplo, utilizaremos a API REST diretamente por meio do HttpClient.
Essa escolha evita acoplar a aplicação a uma biblioteca especĆfica. O repositório do SDK oficial C# foi arquivado em julho de 2026, portanto vale avaliar cuidadosamente seu estado de manutenção antes de adotĆ”-lo em novos projetos.
Estrutura sugerida
PineconeIntegration/
ā
āāā Controllers/
ā āāā DocumentsController.cs
ā
āāā Application/
ā āāā DTOs/
ā ā āāā DocumentRequest.cs
ā ā āāā SearchRequest.cs
ā ā
ā āāā Interfaces/
ā āāā IEmbeddingService.cs
ā āāā IPineconeService.cs
ā
āāā Domain/
ā āāā Entities/
ā āāā Document.cs
ā
āāā Infrastructure/
ā āāā Embeddings/
ā ā āāā EmbeddingService.cs
ā ā
ā āāā Pinecone/
ā āāā PineconeOptions.cs
ā āāā PineconeService.cs
ā
āāā appsettings.json
āāā Program.cs
A separação permite manter as responsabilidades organizadas:
- Api: exposição dos endpoints HTTP.
- Application: contratos, DTOs e regras de aplicação.
- Domain: entidades e conceitos do negócio.
- Infrastructure: integração com serviços externos, embeddings e Pinecone.
š 5. Criando uma conta e configurando o Pinecone
Para utilizar o serviƧo, acesse:
Após criar sua conta:
- Acesse o painel de controle.
- Crie um projeto.
- Gere uma API Key.
- Crie um Index.
- Configure a dimensão dos vetores.
- Selecione a mƩtrica de similaridade.
- Aguarde o Ćndice ficar disponĆvel.
Configuração do Index
Para nosso exemplo, considere:
| Configuração | Valor |
|---|---|
| Nome | dotnet-documents |
| Tipo | Dense Vector |
| Dimension | 384 |
| Metric | Cosine |
| Deployment | Serverless |
Atenção: a dimensão 384 é apenas ilustrativa. Ela precisa corresponder exatamente à dimensão produzida pelo modelo de embeddings escolhido.
A mĆ©trica Cosine Ć© uma opção comum para pesquisas semĆ¢nticas, mas a escolha deve considerar as caracterĆsticas do modelo e da aplicação.
Obtendo o Index Host
Depois de criar o Ćndice, obtenha seu endereƧo de acesso (host).
O formato Ć© semelhante a:
https://dotnet-documents-xxxxx.svc.region.pinecone.io
O endereƧo real serĆ” fornecido pelo Pinecone. NĆ£o utilize um endereƧo fictĆcio na aplicação.
Em produção, prefira utilizar o host especĆfico do Ćndice nas operaƧƵes de dados.
āļø 6. Configurando as variĆ”veis da aplicação
Vamos utilizar o padrão Options do .NET para centralizar as configurações.
PineconeOptions.cs
namespace PineconeIntegration.Infrastructure.Pinecone;
public sealed class PineconeOptions
{
public const string SectionName = "Pinecone";
public string ApiKey { get; set; } = string.Empty;
public string IndexHost { get; set; } = string.Empty;
public string Namespace { get; set; } = "documents";
public int Dimension { get; set; } = 384;
}
appsettings.json
{
"Pinecone": {
"IndexHost": "",
"Namespace": "documents",
"Dimension": 384
}
}
A API Key não deve ser armazenada no arquivo de configuração versionado.
Configure-a por variƔvel de ambiente:
Pinecone__ApiKey="SUA_API_KEY"
Pinecone__IndexHost="https://SEU_INDEX_HOST"
Durante o desenvolvimento, tambĆ©m Ć© possĆvel utilizar o Secret Manager:
dotnet user-secrets init
dotnet user-secrets set "Pinecone:ApiKey" "SUA_API_KEY"
dotnet user-secrets set "Pinecone:IndexHost" "https://SEU_INDEX_HOST"
š 7. Criando o contrato de integração
Vamos definir uma interface para abstrair as operaƧƵes do Pinecone.
IPineconeService.cs
namespace PineconeIntegration.Application.Interfaces;
public interface IPineconeService
{
Task UpsertAsync(
string id,
float[] embedding,
string content,
CancellationToken cancellationToken);
Task<string> SearchAsync(
float[] embedding,
int topK,
CancellationToken cancellationToken);
}
Essa abstração permite trocar a implementação futuramente sem alterar os controllers ou as regras principais da aplicação.
𧮠8. Implementando o serviço de embeddings
Antes de enviar informaƧƵes para o Pinecone, precisamos transformar o texto em um vetor.
Para isso, utilizamos um modelo de embeddings.
Podemos utilizar modelos de provedores externos ou executar um modelo localmente.
Neste exemplo, vamos definir um contrato independente do fornecedor.
IEmbeddingService.cs
namespace PineconeIntegration.Application.Interfaces;
public interface IEmbeddingService
{
Task<float[]> GenerateAsync(
string text,
CancellationToken cancellationToken);
}
EmbeddingService.cs
using PineconeIntegration.Application.Interfaces;
namespace PineconeIntegration.Infrastructure.Embeddings;
public sealed class EmbeddingService : IEmbeddingService
{
public Task<float[]> GenerateAsync(
string text,
CancellationToken cancellationToken)
{
// Exemplo didƔtico.
// Substitua pela chamada real ao modelo de embeddings.
throw new NotImplementedException(
"Configure um provedor real de embeddings.");
}
}
Não devemos utilizar vetores aleatórios ou gerados artificialmente em uma aplicação real.
O modelo precisa produzir embeddings semanticamente consistentes tanto para os documentos armazenados quanto para as consultas.
Regra fundamental: utilize o mesmo modelo e a mesma configuração de dimensão nas duas operações.
š¦ 9. Criando o serviƧo Pinecone com HttpClient
Agora vamos implementar a comunicação com a API REST.
O Pinecone oferece operaƧƵes de Data Plane para armazenar e pesquisar vetores.
Utilizaremos:
POST /vectors/upsertPOST /query
As chamadas serĆ£o direcionadas ao host especĆfico do Ćndice.
PineconeService.cs
using System.Net.Http.Json;
using System.Text.Json;
using PineconeIntegration.Application.Interfaces;
using PineconeIntegration.Infrastructure.Pinecone;
namespace PineconeIntegration.Infrastructure.Pinecone;
public sealed class PineconeService : IPineconeService
{
private readonly HttpClient _httpClient;
private readonly PineconeOptions _options;
private static readonly JsonSerializerOptions JsonOptions =
new(JsonSerializerDefaults.Web);
public PineconeService(
HttpClient httpClient,
Microsoft.Extensions.Options.IOptions<PineconeOptions> options)
{
_httpClient = httpClient;
_options = options.Value;
}
public async Task UpsertAsync(
string id,
float[] embedding,
string content,
CancellationToken cancellationToken)
{
ValidateEmbedding(embedding);
var request = new
{
vectors = new[]
{
new
{
id,
values = embedding,
metadata = new
{
content
}
}
},
@namespace = _options.Namespace
};
using var response = await _httpClient.PostAsJsonAsync(
"/vectors/upsert",
request,
JsonOptions,
cancellationToken);
response.EnsureSuccessStatusCode();
}
public async Task<string> SearchAsync(
float[] embedding,
int topK,
CancellationToken cancellationToken)
{
ValidateEmbedding(embedding);
if (topK is < 1 or > 1000)
{
throw new ArgumentOutOfRangeException(nameof(topK));
}
var request = new
{
vector = embedding,
topK,
includeMetadata = true,
includeValues = false,
@namespace = _options.Namespace
};
using var response = await _httpClient.PostAsJsonAsync(
"/query",
request,
JsonOptions,
cancellationToken);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync(
cancellationToken);
}
private void ValidateEmbedding(float[] embedding)
{
ArgumentNullException.ThrowIfNull(embedding);
if (embedding.Length != _options.Dimension)
{
throw new ArgumentException(
$"Expected {_options.Dimension} dimensions, " +
$"but received {embedding.Length}.");
}
if (embedding.Any(value => !float.IsFinite(value)))
{
throw new ArgumentException(
"Embedding contains invalid numeric values.");
}
}
}
Entendendo a implementação
UpsertAsync
Envia um vetor para o Pinecone com:
- ID Ćŗnico.
- Valores numƩricos do embedding.
- Metadata com o conteĆŗdo original.
- Namespace de armazenamento.
Se o ID jÔ existir, a operação atualiza o registro.
SearchAsync
Recebe o vetor de pesquisa e solicita os registros mais próximos.
O parâmetro topK determina a quantidade mÔxima de resultados solicitados.
A propriedade includeMetadata permite recuperar os dados associados aos vetores.
š 10. Configurando autenticação e injeção de dependĆŖncia
Vamos registrar o HttpClient e os serviços no container de dependências do .NET.
Program.cs
using PineconeIntegration.Application.Interfaces;
using PineconeIntegration.Infrastructure.Embeddings;
using PineconeIntegration.Infrastructure.Pinecone;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services
.AddOptions<PineconeOptions>()
.Bind(builder.Configuration.GetSection(
PineconeOptions.SectionName))
.Validate(
options => !string.IsNullOrWhiteSpace(options.ApiKey),
"Pinecone API Key is required.")
.Validate(
options =>
Uri.TryCreate(
options.IndexHost,
UriKind.Absolute,
out var uri) &&
uri.Scheme == Uri.UriSchemeHttps,
"A valid HTTPS Index Host is required.")
.Validate(
options => options.Dimension > 0,
"Dimension must be greater than zero.")
.ValidateOnStart();
builder.Services.AddHttpClient<IPineconeService, PineconeService>(
(serviceProvider, client) =>
{
var options = serviceProvider
.GetRequiredService<
Microsoft.Extensions.Options.IOptions<PineconeOptions>>()
.Value;
client.BaseAddress = new Uri(
options.IndexHost.TrimEnd('/') + "/");
client.Timeout = TimeSpan.FromSeconds(30);
client.DefaultRequestHeaders.Add(
"Api-Key",
options.ApiKey);
client.DefaultRequestHeaders.Add(
"X-Pinecone-Api-Version",
"2025-10");
});
builder.Services.AddScoped<IEmbeddingService, EmbeddingService>();
var app = builder.Build();
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
A versão da API utilizada no exemplo é 2025-10, conforme a documentação de referência consultada. Antes de publicar em produção, verifique a versão estÔvel mais recente e a compatibilidade dos endpoints utilizados.
š„ 11. Criando o endpoint para cadastrar documentos
Vamos disponibilizar um endpoint para receber textos e armazenar seus respectivos embeddings.
DocumentRequest.cs
using System.ComponentModel.DataAnnotations;
namespace PineconeIntegration.Application.DTOs;
public sealed record DocumentRequest(
[Required]
[StringLength(10000, MinimumLength = 3)]
string Content);
DocumentsController.cs
using Microsoft.AspNetCore.Mvc;
using PineconeIntegration.Application.DTOs;
using PineconeIntegration.Application.Interfaces;
namespace PineconeIntegration.Controllers;
[ApiController]
[Route("api/documents")]
public sealed class DocumentsController : ControllerBase
{
private readonly IPineconeService _pineconeService;
private readonly IEmbeddingService _embeddingService;
public DocumentsController(
IPineconeService pineconeService,
IEmbeddingService embeddingService)
{
_pineconeService = pineconeService;
_embeddingService = embeddingService;
}
[HttpPost]
public async Task<IActionResult> Create(
[FromBody] DocumentRequest request,
CancellationToken cancellationToken)
{
var embedding = await _embeddingService.GenerateAsync(
request.Content,
cancellationToken);
var id = Guid.NewGuid().ToString();
await _pineconeService.UpsertAsync(
id,
embedding,
request.Content,
cancellationToken);
return Created(
$"/api/documents/{id}",
new
{
Id = id,
Message = "Document successfully indexed."
});
}
}
Exemplo de requisição
POST /api/documents
Content-Type: application/json
{
"content": "O .NET 10 permite desenvolver APIs modernas utilizando C#."
}
O processo serĆ”:
- Receber o documento.
- Gerar seu embedding.
- Criar um identificador.
- Enviar o vetor para o Pinecone.
- Retornar o resultado da operação.
š 12. Criando o endpoint de pesquisa semĆ¢ntica
Agora vamos implementar a pesquisa.
SearchRequest.cs
using System.ComponentModel.DataAnnotations;
namespace PineconeIntegration.Application.DTOs;
public sealed record SearchRequest(
[Required]
[StringLength(2000, MinimumLength = 2)]
string Query,
[Range(1, 20)]
int TopK = 5);
Adicione o endpoint ao DocumentsController:
[HttpPost("search")]
public async Task<IActionResult> Search(
[FromBody] SearchRequest request,
CancellationToken cancellationToken)
{
var embedding = await _embeddingService.GenerateAsync(
request.Query,
cancellationToken);
var results = await _pineconeService.SearchAsync(
embedding,
request.TopK,
cancellationToken);
return Ok(new
{
Query = request.Query,
Results = results
});
}
Exemplo de requisição
POST /api/documents/search
Content-Type: application/json
{
"query": "Como desenvolver uma API moderna com C#?",
"topK": 5
}
O Pinecone retornarÔ os registros mais próximos do vetor da consulta.
Cada resultado pode conter:
- ID do vetor.
- Score de similaridade.
- Metadata.
- ConteĆŗdo original, quando armazenado na metadata.
O score representa uma medida de similaridade conforme a mĆ©trica configurada no Ćndice. NĆ£o deve ser interpretado automaticamente como uma porcentagem de confianƧa.
š¤ 13. Integrando Pinecone com RAG
Uma das aplicações mais interessantes do Pinecone é a construção de soluções RAG.
RAG significa Retrieval-Augmented Generation e combina recuperação de informações com geração de respostas por modelos de linguagem.
Como funciona?
Imagine um chatbot corporativo que responde perguntas sobre documentos internos.
O fluxo pode ser:
- O usuƔrio envia uma pergunta.
- A aplicação gera o embedding da pergunta.
- O Pinecone pesquisa os documentos mais relevantes.
- A aplicação recupera os conteúdos encontrados.
- Os conteúdos são adicionados ao contexto do LLM.
- O modelo gera uma resposta fundamentada nas informaƧƵes recuperadas.
Arquitetura RAG
flowchart TD
A["UsuƔrio"] --> B["API .NET 10"]
B --> C["Embedding da pergunta"]
C --> D["Pinecone Vector Search"]
D --> E["Documentos relevantes"]
E --> F["Construção do contexto"]
F --> G["LLM"]
G --> H["Resposta contextualizada"]
H --> A
Essa arquitetura pode ser aplicada em:
- Chatbots de atendimento.
- Assistentes de documentação técnica.
- Sistemas de suporte interno.
- Pesquisa de contratos.
- Consulta de manuais.
- Bases de conhecimento corporativas.
Importante: a recuperação de documentos não garante, por si só, que o LLM responderÔ corretamente. à necessÔrio controlar o contexto, as permissões, as fontes e a qualidade das respostas.
𧱠14. Boas prÔticas de arquitetura e desenvolvimento
Para utilizar Pinecone em aplicaƧƵes corporativas, recomendo observar alguns pontos.
š SeguranƧa
- Nunca exponha a API Key no frontend.
- Utilize variƔveis de ambiente ou um cofre de segredos.
- Restrinja as permissƵes das credenciais.
- Utilize HTTPS.
- Implemente autenticação e autorização na API .NET.
- Separe os namespaces conforme as necessidades de isolamento.
- Não permita que o usuÔrio escolha livremente namespaces sem validação.
ā” Performance
- Utilize
IHttpClientFactory. - Configure timeout adequado.
- Avalie operaƧƵes em lote para grandes volumes.
- Evite gerar embeddings repetidos para conteúdos que não mudaram.
- Utilize IDs estƔveis quando precisar atualizar documentos.
- Recupere apenas os metadados necessƔrios.
- Avalie o custo e a latĆŖncia das consultas.
š Observabilidade
Monitore:
- Tempo de geração dos embeddings.
- Tempo de resposta do Pinecone.
- Quantidade de vetores cadastrados.
- Quantidade de resultados recuperados.
- Erros de autenticação e comunicação.
- Consumo e custos associados às operações.
Evite registrar API Keys, documentos confidenciais ou informaƧƵes pessoais nos logs.
š§© ConsistĆŖncia dos embeddings
O modelo de embeddings utilizado na indexação deve ser compatĆvel com o modelo utilizado na consulta.
Se trocar o modelo, a dimensĆ£o ou a estratĆ©gia de geração, considere criar um novo Ćndice e reprocessar os documentos.
𧪠15. Estratégia de testes
Uma integração bem estruturada também precisa de testes.
SugestƵes:
| CenƔrio | Resultado esperado |
|---|---|
| Inserção de documento | Vetor armazenado |
| Atualização de documento | Registro atualizado |
| Consulta vƔlida | Resultados encontrados |
| Vetor com dimensão incorreta | Validação rejeitada |
| API Key invÔlida | Erro de autenticação |
| Index Host incorreto | Falha de comunicação |
| Pinecone indisponĆvel | Tratamento de falha |
| Consulta sem resultados | Lista vazia |
| Namespace incorreto | Isolamento respeitado |
Uma boa estratégia é utilizar mocks para testar os serviços de aplicação e testes de integração controlados para validar a comunicação real com o Pinecone.
šļø 16. Evoluindo a solução
Depois de implementar as operaƧƵes bƔsicas, podemos evoluir a arquitetura para suportar cenƔrios mais complexos.
Funcionalidades futuras
- Upload e processamento de PDF.
- Divisão de documentos em chunks.
- Pipeline assĆncrono com RabbitMQ.
- Processamento em lote.
- Integração com Azure OpenAI ou outros provedores de LLM.
- Busca hĆbrida: semĆ¢ntica e textual.
- Filtros por metadata.
- Controle de acesso por usuÔrio e organização.
- Versionamento de documentos.
- Estratégias de reindexação.
- Monitoramento com OpenTelemetry.
ā ļø 17. Pontos importantes antes de utilizar em produção
O exemplo apresentado demonstra o fluxo essencial, mas uma aplicação real precisa de algumas evoluções:
- Implementar um provedor real de embeddings.
- Criar uma estratƩgia de chunking para documentos extensos.
- Implementar polĆticas de retry e tratamento de erros transitórios, respeitando os limites do serviƧo.
- Definir limites de tamanho e quantidade de registros por requisição.
- Criar uma estratégia de atualização e exclusão de documentos.
- Garantir isolamento entre clientes e organizaƧƵes.
- Validar a compatibilidade entre dimensão e modelo de embeddings.
- Implementar monitoramento de custos e latĆŖncia.
- Tratar indisponibilidade do serviƧo externo.
- Avaliar a retenção e proteção dos dados armazenados.
Outro detalhe importante: Pinecone não substitui necessariamente um banco relacional. Uma arquitetura pode utilizar SQL Server ou PostgreSQL para os dados transacionais e Pinecone para a recuperação semântica.
šÆ 18. ConclusĆ£o
A integração entre .NET 10 e Pinecone abre possibilidades interessantes para aplicações que precisam trabalhar com Inteligência Artificial, recuperação de conhecimento e pesquisas semânticas.
Com uma arquitetura organizada, utilizando interfaces, injeção de dependência e HttpClient, conseguimos manter a integração desacoplada e preparada para evoluções futuras.
O Pinecone pode atuar como uma camada especializada de recuperação vetorial, enquanto o .NET 10 permanece responsÔvel pelas regras de negócio, exposição das APIs, segurança e orquestração dos serviços.
Mais do que integrar um banco de dados, estamos construindo uma base para aplicações inteligentes, capazes de recuperar informações pelo significado e não apenas pela correspondência exata de palavras.
O futuro das aplicações modernas não estÔ somente em armazenar dados, mas também em conseguir interpretar, relacionar e recuperar conhecimento.
š ReferĆŖncias e documentação
- Pinecone ā Documentação oficial
- Pinecone ā REST API Reference
- Pinecone ā GitHub C# Client
- Microsoft ā IHttpClientFactory
- Microsoft ā .NET 10
š¤ Conecte-se Comigo
š¼ LinkedIn
š» Dev.to
āļø Medium
š° Substack
š Compartilhando conhecimento sobre .NET, arquitetura de software, cloud computing, DevOps e InteligĆŖncia Artificial.
Top comments (0)