fix: 修复知识库索引并发与向量化边界
- 复用 Lucene 和 Elasticsearch 客户端并支持有界批量写入与删除 - 记录脱敏后的 Embedding 失败请求与完整响应 - 为 BGE-M3 分块统一增加上下文硬上限
This commit is contained in:
@@ -11,13 +11,19 @@ import com.easyagents.core.store.VectorData;
|
||||
import com.easyagents.core.util.JSONUtil;
|
||||
import com.easyagents.core.util.Maps;
|
||||
import com.easyagents.core.util.StringUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class OpenAIEmbeddingModel extends BaseEmbeddingModel<OpenAIEmbeddingConfig> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(OpenAIEmbeddingModel.class);
|
||||
private static final String REDACTED_HEADER_VALUE = "[REDACTED]";
|
||||
|
||||
private HttpClient httpClient = new HttpClient();
|
||||
|
||||
public OpenAIEmbeddingModel(OpenAIEmbeddingConfig config) {
|
||||
@@ -40,27 +46,45 @@ public class OpenAIEmbeddingModel extends BaseEmbeddingModel<OpenAIEmbeddingConf
|
||||
|
||||
String payload = promptToEmbeddingsPayload(document, options, config);
|
||||
String endpoint = config.getEndpoint();
|
||||
String requestUrl = endpoint + config.getRequestPath();
|
||||
// https://platform.openai.com/docs/api-reference/embeddings/create
|
||||
String response = httpClient.post(endpoint + config.getRequestPath(), headers, payload);
|
||||
String response = httpClient.post(requestUrl, headers, payload);
|
||||
|
||||
if (StringUtil.noText(response)) {
|
||||
logResponseParsingFailure(
|
||||
"response is null or empty",
|
||||
requestUrl,
|
||||
headers,
|
||||
payload,
|
||||
response
|
||||
);
|
||||
throw new ModelException("response is null or empty.");
|
||||
}
|
||||
|
||||
JSONObject jsonObject = JSON.parseObject(response);
|
||||
String errorMessage = JSONUtil.detectErrorMessage(jsonObject);
|
||||
if (errorMessage != null) {
|
||||
throw new ModelException(errorMessage);
|
||||
}
|
||||
try {
|
||||
JSONObject jsonObject = JSON.parseObject(response);
|
||||
String errorMessage = JSONUtil.detectErrorMessage(jsonObject);
|
||||
if (errorMessage != null) {
|
||||
logResponseParsingFailure(errorMessage, requestUrl, headers, payload, response);
|
||||
throw new ModelException(errorMessage);
|
||||
}
|
||||
|
||||
VectorData vectorData = new VectorData();
|
||||
double[] embedding = JSONUtil.readDoubleArray(jsonObject, "$.data[0].embedding");
|
||||
if (embedding == null || embedding.length == 0) {
|
||||
throw new ModelException(buildMissingEmbeddingMessage());
|
||||
}
|
||||
vectorData.setVector(embedding);
|
||||
VectorData vectorData = new VectorData();
|
||||
double[] embedding = JSONUtil.readDoubleArray(jsonObject, "$.data[0].embedding");
|
||||
if (embedding == null || embedding.length == 0) {
|
||||
String missingEmbeddingMessage = buildMissingEmbeddingMessage();
|
||||
logResponseParsingFailure(missingEmbeddingMessage, requestUrl, headers, payload, response);
|
||||
throw new ModelException(missingEmbeddingMessage);
|
||||
}
|
||||
vectorData.setVector(embedding);
|
||||
|
||||
return vectorData;
|
||||
return vectorData;
|
||||
} catch (ModelException e) {
|
||||
throw e;
|
||||
} catch (RuntimeException e) {
|
||||
logResponseParsingFailure(e.getMessage(), requestUrl, headers, payload, response);
|
||||
throw new ModelException("Failed to parse embedding response.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,4 +138,35 @@ public class OpenAIEmbeddingModel extends BaseEmbeddingModel<OpenAIEmbeddingConf
|
||||
+ ", endpoint=" + config.getEndpoint()
|
||||
+ ", requestPath=" + config.getRequestPath();
|
||||
}
|
||||
|
||||
private void logResponseParsingFailure(String reason,
|
||||
String requestUrl,
|
||||
Map<String, String> requestHeaders,
|
||||
String requestBody,
|
||||
String responseBody) {
|
||||
LOG.error(
|
||||
"Embedding response parsing failed: reason={}\n"
|
||||
+ "requestUrl={}\n"
|
||||
+ "requestHeaders={}\n"
|
||||
+ "requestBody={}\n"
|
||||
+ "responseBody={}",
|
||||
reason,
|
||||
requestUrl,
|
||||
sanitizeHeadersForLogging(requestHeaders),
|
||||
requestBody,
|
||||
responseBody
|
||||
);
|
||||
}
|
||||
|
||||
static Map<String, String> sanitizeHeadersForLogging(Map<String, String> headers) {
|
||||
Map<String, String> sanitizedHeaders = new LinkedHashMap<>();
|
||||
if (headers == null) {
|
||||
return sanitizedHeaders;
|
||||
}
|
||||
headers.forEach((name, value) -> sanitizedHeaders.put(
|
||||
name,
|
||||
"Authorization".equalsIgnoreCase(name) ? REDACTED_HEADER_VALUE : value
|
||||
));
|
||||
return sanitizedHeaders;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user