从零开始:用Java和Pinecone构建内容生成应用

云信安装大师
90
AI 质量分
11 5 月, 2025
4 分钟阅读
0 阅读

从零开始:用Java和Pinecone构建内容生成应用

引言

在当今AI驱动的世界中,构建能够理解和生成内容的应用程序变得越来越重要。本文将带你从零开始,使用Java和Pinecone向量数据库构建一个简单的内容生成应用。我们将利用文本嵌入技术将内容转换为向量,存储在Pinecone中,然后实现相似内容检索和生成功能。

准备工作

环境要求

  • JDK 11或更高版本
  • Maven 3.6+
  • Pinecone账号(免费注册)
  • OpenAI API密钥(可选,用于文本嵌入)

项目初始化

创建一个新的Maven项目并添加以下依赖:

代码片段
<dependencies>
    <!-- Pinecone Java客户端 -->
    <dependency>
        <groupId>io.pinecone</groupId>
        <artifactId>pinecone-client</artifactId>
        <version>0.3.0</version>
    </dependency>

    <!-- OpenAI Java客户端 -->
    <dependency>
        <groupId>com.theokanning.openai-gpt3-java</groupId>
        <artifactId>client</artifactId>
        <version>0.11.1</version>
    </dependency>

    <!-- JSON处理 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.14.1</version>
    </dependency>

    <!-- 日志 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.36</version>
    </dependency>
</dependencies>

Pinecone设置

1. 创建Pinecone索引

首先登录Pinecone控制台(https://app.pinecone.io)并创建一个新索引:
– 名称:content-index
– 维度:1536(这是OpenAI text-embedding-ada-002模型的输出维度)
– 度量:cosine

2. 获取API密钥

在Pinecone控制台的”API Keys”部分获取你的API密钥和环境名称。

核心代码实现

1. Pinecone服务类

代码片段
import io.pinecone.clients.Pinecone;
import io.pinecone.clients.Index;
import io.pinecone.proto.UpsertResponse;
import io.pinecone.proto.QueryResponse;
import io.pinecone.proto.Vector;

public class PineconeService {
    private final Index index;

    public PineconeService(String apiKey, String environment, String indexName) {
        Pinecone pinecone = new Pinecone.Builder(apiKey)
                .withEnvironment(environment)
                .build();

        this.index = pinecone.getIndexConnection(indexName);
    }

    // 存储向量到Pinecone
    public void upsertVector(String id, float[] embedding, String text) {
        Vector vector = Vector.newBuilder()
                .setId(id)
                .addAllValues(Arrays.asList(Floats.asList(embedding)))
                .putMetadata("text", text)
                .build();

        UpsertResponse response = index.upsert(Collections.singletonList(vector));

        if (response.getUpsertedCount() != 1) {
            throw new RuntimeException("Failed to upsert vector");
        }
    }

    // 查询相似内容
    public List<String> querySimilarContent(float[] embedding, int topK) {
        QueryResponse response = index.query(
                embedding,
                topK,
                true, // includeMetadata
                true, // includeValues
                null); // filter

        return response.getMatchesList().stream()
                .map(match -> match.getMetadata().getFieldsMap().get("text").getStringValue())
                .collect(Collectors.toList());
    }
}

2. OpenAI嵌入服务类

代码片段
import com.theokanning.openai.service.OpenAiService;
import com.theokanning.openai.embedding.EmbeddingRequest;
import com.theokanning.openai.embedding.EmbeddingResult;

public class OpenAIService {
    private final OpenAiService service;

    public OpenAIService(String apiKey) {
        this.service = new OpenAiService(apiKey);
    }

    // 获取文本的嵌入向量
    public float[] getEmbedding(String text) {
        EmbeddingRequest request = EmbeddingRequest.builder()
                .model("text-embedding-ada-002")
                .input(Collections.singletonList(text))
                .build();

        EmbeddingResult result = service.createEmbeddings(request);

        if (result.getData() == null || result.getData().isEmpty()) {
            throw new RuntimeException("Failed to get embedding");
        }

        // 将Double列表转换为float数组
        return result.getData().get(0).getEmbedding().stream()
                .map(Double::floatValue)
                .collect(Collectors.toList())
                .toArray(new float[0]);
    }
}

3. 主应用类

代码片段
import java.util.*;

public class ContentGeneratorApp {

    private final OpenAIService openAIService;
    private final PineconeService pineconeService;

    public ContentGeneratorApp(String openaiApiKey, String pineconeApiKey, 
                              String pineconeEnv, String indexName) {
        this.openAIService = new OpenAIService(openaiApiKey);
        this.pineconeService = new PineconeService(pineconeApiKey, pineconeEnv, indexName);
    }

    // 存储内容到Pinecone
    public void storeContent(String id, String content) {
        float[] embedding = openAIService.getEmbedding(content);
        pineconeService.upsertVector(id, embedding, content);

        System.out.println("Stored content with ID: " + id);
    }

    // 查找相似内容并生成新的相关内容
    public List<String> generateRelatedContent(String queryText, int numResults) {
        float[] queryEmbedding = openAIService.getEmbedding(queryText);

        List<String> similarContents = pineconeService.querySimilarContent(
            queryEmbedding, numResults);

        System.out.println("\nSimilar contents found:");

         // TODO:这里可以添加更复杂的内容生成逻辑

         return similarContents.stream()
                 .map(content -> "Related: " + content)
                 .collect(Collectors.toList());
     }

     public static void main(String[] args) {
         // 从环境变量或配置文件中获取这些值更安全
         String openaiApiKey = "your-openai-api-key";
         String pineconeApiKey = "your-pineone-api-key";
         String pineoneEnv = "your-pinenv";
         String indexName = "content-index";

         ContentGeneratorApp app = new ContentGeneratorApp(
             openaiApiKey, pineoneApiKey, pineoneEnv, indexName);

         // 示例数据 - 实际应用中可以从文件或数据库加载更多数据
         app.storeContent("1", "Java is a popular programming language");
         app.storeContent("2", "Python is widely used in data science");
         app.storeContent("3", "JavaScript powers modern web applications");

         // Wait for indexing to complete (在实际应用中需要更健壮的等待机制)
         try { Thread.sleep(2000); } catch (InterruptedException e) {}

         List<String> relatedContents = app.generateRelatedContent(
             "programming languages", 
             2);

         System.out.println("\nGenerated related content:");
         relatedContents.forEach(System.out::println);
     }
}

进阶功能扩展

1.增强内容生成

你可以集成OpenAI的GPT模型来增强内容生成:

代码片段
public List<String> generateEnhancedContent(String queryText, int numResults) {
   float[] queryEmbedding = openAIService.getEmbedding(queryText);
   List<String> similarContents = pineconseService.querySimilarContent(
       queryEmbedding, numResults);

   OpenAiService service = new OpenAiService(openaiApiKey);

   return similarContents.stream()
       .map(content -> {
           CompletionRequest completionRequest = CompletionRequest.builder()
               .prompt("Based on the following content: \n" + content + 
                       "\nGenerate a related paragraph:")
               .model("text-davinci-003")
               .maxTokens(150)
               .build();

           return service.createCompletion(completionRequest)
               .getChoices().get(0).getText();
       })
       .collect(Collectors.toList());
}

2.Python代码示例(可选)

如果你更喜欢使用Python处理某些部分,这里是一个简单的Python脚本示例:

代码片段
import openai
import pineone

# Initialize clients
openai.api_key = "your-openai-key"
pineone.init(api_key="your-pinenv-key", environment="us-west1-gcp")

# Get embedding from OpenAI
def get_embedding(text):
   response = openai.Embedding.create(
       input=[text],
       model="text-embedding-ada-002"
   )
   return response['data'][0]['embedding']

# Store in Pinenvne example (for comparison with Java version)
def store_content(index_name, doc_id, text):
   index=pineone.index(index_name)
   vector=get_embedding(text)

   index.update(
       id=doc_id,
       values=vector,
       metadata={"text": text}
   )

最佳实践和注意事项

1.批量处理:当有大量文档时,使用批量upsert操作而不是单个插入。

2.错误处理:添加重试逻辑处理API限速和暂时性错误。

3.安全性
-不要将API密钥硬编码在源代码中,使用环境变量或安全配置存储。
-考虑为生产环境实现访问控制和审计日志。

4.性能优化
-缓存频繁查询的嵌入结果。
-考虑异步处理大型文档集合。

5.成本控制
-监控API调用量以避免意外费用。
-对于大型项目,考虑本地嵌入模型以减少OpenAI API成本。

总结

本文展示了如何使用Java和Pinenvne构建一个基础的内容生成应用。关键步骤包括:

1.使用OpenAI获取文本嵌入向量
2.将这些向量存储在Pinenvne中以实现高效相似性搜索
3.基于查询找到相关内容
4.(可选)使用GPT模型增强生成的内容

通过结合这些技术,你可以构建强大的语义搜索、推荐系统和内容生成应用。随着你对这些工具越来越熟悉,可以考虑添加更多高级功能如多模态搜索、个性化推荐等。

原创 高质量