Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CU-865cn6kqn Model capabilities and AIScope simplification. #214

Merged
merged 27 commits into from
Jul 3, 2023
Merged
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f5058b6
Generic AI client and models with open-ai client impl from https://gi…
raulraja Jun 21, 2023
a629d15
type LLM models based on their capabilities and type the operations
raulraja Jun 21, 2023
471497a
add token as parameter to `openAI` fn falling back to env variable
raulraja Jun 22, 2023
dd47c87
add config as optional parameter
raulraja Jun 22, 2023
da80199
Merge branch 'main' into open-ai-typed-models
raulraja Jun 22, 2023
76d0e9e
remove old config
raulraja Jun 22, 2023
f631907
Merge remote-tracking branch 'origin/main' into open-ai-typed-models
raulraja Jun 26, 2023
5d44d36
Merge remote-tracking branch 'origin/main' into open-ai-typed-models
raulraja Jun 28, 2023
3fe0656
adapt to latest changes from main and new java module
raulraja Jun 28, 2023
4a89c79
Merge branch 'main' into open-ai-typed-models
nomisRev Jun 29, 2023
6feeffa
Merge remote-tracking branch 'origin/main' into open-ai-typed-models
raulraja Jun 29, 2023
7512191
have openai be its own module that depends on xef-core. kotlin, scala…
raulraja Jun 29, 2023
d6c9f18
Merge remote-tracking branch 'origin/open-ai-typed-models' into open-…
raulraja Jun 29, 2023
1103cdc
fix bug in scala fn name for serialization
raulraja Jun 29, 2023
bd097c0
make AIClient : AutoCloseable
raulraja Jun 29, 2023
ef1c24c
Rename enum cases
raulraja Jun 29, 2023
c5a70f0
Rename to TEXT_EMBEDDING_ADA_002
raulraja Jun 29, 2023
e849bff
Fix AIClient close expectation
raulraja Jun 29, 2023
a586637
Progress with models
raulraja Jun 30, 2023
4800420
Refactor to have models typed and increase ergonomics
raulraja Jul 1, 2023
4b902ab
Merge remote-tracking branch 'origin/main' into gpt-4all-aiclient
raulraja Jul 1, 2023
8f5d9cb
Loading embeddings and tokenizer from huggingface, dynamic loading of…
raulraja Jul 2, 2023
99bdb64
remove non used repositories
raulraja Jul 2, 2023
a1b8736
Fix functions model to GPT_3_5_TURBO_FUNCTIONS and example without AI…
raulraja Jul 2, 2023
48dccec
remove unused import
raulraja Jul 2, 2023
ef49ba7
Small suggestions
diesalbla Jul 3, 2023
b9b6f05
More small suggestions
diesalbla Jul 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Small suggestions
diesalbla committed Jul 3, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit ef49ba750f5fbb4e057ce64e976c6e28b7930b21
24 changes: 10 additions & 14 deletions core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Chat.kt
Original file line number Diff line number Diff line change
@@ -51,32 +51,28 @@ interface Chat : LLM {
return totalLeftTokens
}

fun buildChatRequest(): ChatCompletionRequest {
val messages: List<Message> = listOf(Message(Role.USER, promptWithContext, Role.USER.name))
return ChatCompletionRequest(
val userMessage = Message(Role.USER, promptWithContext, Role.USER.name)
fun buildChatRequest(): ChatCompletionRequest =
ChatCompletionRequest(
model = name,
user = promptConfiguration.user,
messages = messages,
messages = listOf(userMessage),
n = promptConfiguration.numberOfPredictions,
temperature = promptConfiguration.temperature,
maxTokens = checkTotalLeftChatTokens(messages)
maxTokens = checkTotalLeftChatTokens(listOf(userMessage))
)
}

fun chatWithFunctionsRequest(): ChatCompletionRequestWithFunctions {
val firstFnName: String? = functions.firstOrNull()?.name
val messages: List<Message> = listOf(Message(Role.USER, promptWithContext, Role.USER.name))
return ChatCompletionRequestWithFunctions(
fun chatWithFunctionsRequest(): ChatCompletionRequestWithFunctions =
ChatCompletionRequestWithFunctions(
model = name,
user = promptConfiguration.user,
messages = messages,
messages = listOf(userMessage),
n = promptConfiguration.numberOfPredictions,
temperature = promptConfiguration.temperature,
maxTokens = checkTotalLeftChatTokens(messages),
maxTokens = checkTotalLeftChatTokens(listOf(userMessage)),
functions = functions,
functionCall = mapOf("name" to (firstFnName ?: ""))
functionCall = mapOf("name" to (functions.firstOrNull()?.name ?: ""))
)
}

return when (this) {
is ChatWithFunctions ->
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.xebia.functional.gpt4all

import ai.djl.huggingface.tokenizers.HuggingFaceTokenizer
import com.xebia.functional.xef.embeddings.Embedding as XefEmbedding
import com.xebia.functional.xef.embeddings.Embeddings
import com.xebia.functional.xef.llm.models.embeddings.Embedding
import com.xebia.functional.xef.llm.models.embeddings.EmbeddingRequest
@@ -15,7 +16,7 @@ class HuggingFaceLocalEmbeddings(name: String, artifact: String) : com.xebia.fun
override val name: String = HuggingFaceLocalEmbeddings::class.java.canonicalName

override suspend fun createEmbeddings(request: EmbeddingRequest): EmbeddingResult {
val embedings = tokenizer.batchEncode(request.input)
val embeddings = tokenizer.batchEncode(request.input)
return EmbeddingResult(
data = embedings.mapIndexed { n, em -> Embedding("embedding", em.ids.map { it.toFloat() }, n) },
usage = Usage.ZERO
@@ -26,19 +27,12 @@ class HuggingFaceLocalEmbeddings(name: String, artifact: String) : com.xebia.fun
texts: List<String>,
chunkSize: Int?,
requestConfig: RequestConfig
): List<com.xebia.functional.xef.embeddings.Embedding> {
val encodings = tokenizer.batchEncode(texts)
return encodings.mapIndexed { n, em ->
com.xebia.functional.xef.embeddings.Embedding(
em.ids.map { it.toFloat() },
)
): List<XefEmbedding> =
tokenizer.batchEncode(texts).mapIndexed { n, em ->
XefEmbedding(em.ids.map { it.toFloat() })
}
}

override suspend fun embedQuery(
text: String,
requestConfig: RequestConfig
): List<com.xebia.functional.xef.embeddings.Embedding> =
override suspend fun embedQuery(text: String, requestConfig: RequestConfig): List<XefEmbedding> =
embedDocuments(listOf(text), null, requestConfig)

companion object {
Original file line number Diff line number Diff line change
@@ -61,16 +61,14 @@ suspend fun <A> CoreAIScope.prompt(
isLenient = true
},
promptConfiguration: PromptConfiguration = PromptConfiguration.DEFAULTS,
): A {
val functions = generateCFunction(serializer.descriptor)
return model.prompt(
): A =
model.prompt(
prompt,
context,
functions,
generateCFunction(serializer.descriptor),
{ json.decodeFromString(serializer, it) },
promptConfiguration
)
}

@OptIn(ExperimentalSerializationApi::class)
private fun generateCFunction(descriptor: SerialDescriptor): List<CFunction> {
Original file line number Diff line number Diff line change
@@ -8,7 +8,6 @@ import com.aallam.openai.api.completion.CompletionRequest as OpenAICompletionReq
import com.aallam.openai.api.completion.TextCompletion
import com.aallam.openai.api.completion.completionRequest
import com.aallam.openai.api.core.Usage as OpenAIUsage
import com.aallam.openai.api.embedding.EmbeddingRequest as OpenAIEmbeddingRequest
import com.aallam.openai.api.embedding.EmbeddingResponse
import com.aallam.openai.api.embedding.embeddingRequest
import com.aallam.openai.api.image.ImageCreation
@@ -52,27 +51,60 @@ class OpenAIModel(
request: ChatCompletionRequest
): ChatCompletionResponse {
val response = client.chatCompletion(toChatCompletionRequest(request))
return chatCompletionResult(response)
return ChatCompletionResponse(
id = response.id,
`object` = response.model.id,
created = response.created,
model = response.model.id,
choices = response.choices.map { chatCompletionChoice(it) },
usage = usage(response.usage)
)
}

@OptIn(BetaOpenAI::class)
override suspend fun createChatCompletionWithFunctions(
request: ChatCompletionRequestWithFunctions
): ChatCompletionResponseWithFunctions {
val response = client.chatCompletion(toChatCompletionRequestWithFunctions(request))
return chatCompletionResultWithFunctions(response)

fun chatCompletionChoiceWithFunctions(choice: ChatChoice): ChoiceWithFunctions =
ChoiceWithFunctions(
message =
choice.message?.let {
MessageWithFunctionCall(
role = it.role.role,
content = it.content,
name = it.name,
functionCall = it.functionCall?.let { FnCall(it.name, it.arguments) }
)
},
finishReason = choice.finishReason,
index = choice.index,
)

return ChatCompletionResponseWithFunctions(
id = response.id,
`object` = response.model.id,
created = response.created,
model = response.model.id,
choices = response.choices.map { chatCompletionChoiceWithFunctions(it) },
usage = usage(response.usage)
)
}

override suspend fun createEmbeddings(request: EmbeddingRequest): EmbeddingResult {
val response = client.embeddings(toEmbeddingRequest(request))
return embeddingResult(response)
val openAIRequest = embeddingRequest {
model = ModelId(request.model)
input = request.input
user = request.user
}

return embeddingResult(client.embeddings(openAIRequest))
}

@OptIn(BetaOpenAI::class)
override suspend fun createImages(request: ImagesGenerationRequest): ImagesGenerationResponse {
val response = client.imageURL(toImageCreationRequest(request))
return imageResult(response)
}
override suspend fun createImages(request: ImagesGenerationRequest): ImagesGenerationResponse =
imageResult(client.imageURL(toImageCreationRequest(request)))

private fun toCompletionRequest(request: CompletionRequest): OpenAICompletionRequest =
completionRequest {
@@ -118,46 +150,6 @@ class OpenAIModel(
totalTokens = usage?.totalTokens,
)

@OptIn(BetaOpenAI::class)
private fun chatCompletionResult(response: ChatCompletion): ChatCompletionResponse =
ChatCompletionResponse(
id = response.id,
`object` = response.model.id,
created = response.created,
model = response.model.id,
choices = response.choices.map { chatCompletionChoice(it) },
usage = usage(response.usage)
)

@OptIn(BetaOpenAI::class)
private fun chatCompletionResultWithFunctions(
response: ChatCompletion
): ChatCompletionResponseWithFunctions =
ChatCompletionResponseWithFunctions(
id = response.id,
`object` = response.model.id,
created = response.created,
model = response.model.id,
choices = response.choices.map { chatCompletionChoiceWithFunctions(it) },
usage = usage(response.usage)
)

@OptIn(BetaOpenAI::class)
private fun chatCompletionChoiceWithFunctions(choice: ChatChoice): ChoiceWithFunctions =
ChoiceWithFunctions(
message =
choice.message?.let {
MessageWithFunctionCall(
role = it.role.role,
content = it.content,
name = it.name,
functionCall = it.functionCall?.let { FnCall(it.name, it.arguments) }
)
},
finishReason = choice.finishReason,
index = choice.index,
)

@OptIn(BetaOpenAI::class)
private fun chatCompletionChoice(choice: ChatChoice): Choice =
Choice(
@@ -258,13 +250,6 @@ class OpenAIModel(
usage = usage(response.usage)
)

private fun toEmbeddingRequest(request: EmbeddingRequest): OpenAIEmbeddingRequest =
embeddingRequest {
model = ModelId(request.model)
input = request.input
user = request.user
}

@OptIn(BetaOpenAI::class)
private fun imageResult(response: List<ImageURL>): ImagesGenerationResponse =
ImagesGenerationResponse(data = response.map { ImageGenerationUrl(it.url) })