Skip to content

Commit

Permalink
hugging face basic llm endpoint is implemneted
Browse files Browse the repository at this point in the history
  • Loading branch information
huzaifansari54 committed Nov 12, 2024
1 parent 194534c commit 072770e
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
void main() {
// TODO
// ignore_for_file: avoid_print, unused_element

import 'package:langchain_core/chat_models.dart';

import 'package:langchain_huggingface/src/llm/huggingface_inference.dart';

void main() async {
// Uncomment the example you want to run:
await _example1();
// await _example2();
}

/// The most basic building block of LangChain is calling an LLM on some input.
Future<void> _example1() async {
final huggingFace = HuggingfaceInference(
model: 'gpt2',
apiKey: '...Hugging-face-api-key',
);
final result = await huggingFace('Who are you?');
print(result);
}
2 changes: 2 additions & 0 deletions packages/langchain_huggingface/lib/langchain_huggingface.dart
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/// Hugging Face module for LangChain.dart.
library;

export 'src/llm/llm.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import 'package:huggingface_client/huggingface_client.dart';
import 'package:langchain_core/llms.dart';
import 'package:langchain_core/src/prompts/types.dart';
import 'package:meta/meta.dart';
import 'mappers.dart';
import 'types.dart';

@immutable
class HuggingfaceInference extends BaseLLM<HuggingFaceOptions> {
HuggingfaceInference({
required this.model,
required this.apiKey,
super.defaultOptions = const HuggingFaceOptions(),
}) : _apiClient = InferenceApi(_getclient(apiKey));
final InferenceApi _apiClient;
final String apiKey;
final String model;

@override
Future<LLMResult> invoke(PromptValue input,
{HuggingFaceOptions? options}) async {
final parameters = ApiQueryNLPTextGeneration(
inputs: input.toString(),
temperature: options?.temperature ?? 1.0,
topK: options?.topK ?? 0,
topP: options?.topP ?? 0.0,
maxTime: options?.maxTime ?? -1.0,
returnFullText: options?.returnFullText ?? true,
repetitionPenalty: options?.repetitionPenalty ?? -1,
doSample: options?.doSample ?? true,
maxNewTokens: options?.maxNewTokens ?? -1,
options: InferenceOptions(
useCache: options?.useCache ?? true,
waitForModel: options?.waitForModel ?? false));
final result = await _apiClient.queryNLPTextGeneration(
taskParameters: parameters, model: model);

return result![0]!.toLLMResult();
}

static InferenceApiClient _getclient(String apikey) =>
HuggingFaceClient.getInferenceClient(
apikey, HuggingFaceClient.inferenceBasePath);

@override
String get modelType => 'llm';
@override
Future<List<int>> tokenize(PromptValue promptValue,
{HuggingFaceOptions? options}) async {
// TODO: implement tokenize
throw UnimplementedError();
}
}
2 changes: 2 additions & 0 deletions packages/langchain_huggingface/lib/src/llm/llm.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'huggingface_inference.dart';
export 'types.dart';
15 changes: 15 additions & 0 deletions packages/langchain_huggingface/lib/src/llm/mappers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:huggingface_client/huggingface_client.dart';
import 'package:langchain_core/language_models.dart';
import 'package:langchain_core/llms.dart';

extension HuggingFaceResponseMapper on ApiResponseNLPTextGeneration {
//map to
LLMResult toLLMResult() {
return LLMResult(
id: 'id',
output: generatedText,
finishReason: FinishReason.unspecified,
metadata: {},
usage: const LanguageModelUsage());
}
}
124 changes: 124 additions & 0 deletions packages/langchain_huggingface/lib/src/llm/types.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import 'package:langchain_core/llms.dart';
import 'package:langchain_core/src/language_models/types.dart';
import 'package:meta/meta.dart';

@immutable
class HuggingFaceOptions extends LLMOptions {
const HuggingFaceOptions(
{this.topK,
this.topP,
super.model,
this.temperature,
this.repetitionPenalty,
this.maxNewTokens,
this.maxTime,
this.returnFullText,
this.numReturnSequences,
this.useCache,
this.waitForModel,
this.doSample});

/// (Default: true). Boolean. There is a cache layer on the inference API to speedup requests we have already seen.
/// Most models can use those results as is as models are deterministic (meaning the results will be the same anyway).
/// However if you use a non deterministic model, you can set this parameter to prevent the caching mechanism from being
/// used resulting in a real new query.
final bool? useCache;

/// (Default: false) Boolean. If the model is not ready, wait for it instead of receiving 503. It limits the number of requests
/// required to get your inference done. It is advised to only set this flag to true after receiving a 503
/// error as it will limit hanging in your application to known places.
final bool? waitForModel;

/// (Default: None). Integer to define the top tokens considered within the sample operation to create new text.
final int? topK;

/// (Default: None). Float to define the tokens that are within the sample operation of text generation.
/// Add tokens in the sample for more probable to least probable until the sum of the probabilities
/// is greater than top_p.
final double? topP;

/// (Default: 1.0). Float (0.0-100.0). The temperature of the sampling operation. 1 means regular sampling,
/// 0 means always take the highest score, 100.0 is getting closer to uniform probability.
final double? temperature;

/// (Default: None). Float (0.0-100.0). The more a token is used within generation the more it is penalized
/// to not be picked in successive generation passes.
final double? repetitionPenalty;

/// (Default: None). Int (0-250). The amount of new tokens to be generated, this does not include the input
/// length it is a estimate of the size of generated text you want. Each new tokens slows down the request,
/// so look for balance between response times and length of text generated.
final int? maxNewTokens;

/// (Default: None). Float (0-120.0). The amount of time in seconds that the query should take maximum.
/// Network can cause some overhead so it will be a soft limit. Use that in combination
/// with [maxNewTokens] for best results.
final double? maxTime;

/// (Default: True). Bool. If set to False, the return results will not contain the
/// original query making it easier for prompting.
final bool? returnFullText;

/// (Default: 1). Integer. The number of proposition you want to be returned.
final int? numReturnSequences;

/// (Optional: True). Bool. Whether or not to use sampling, use greedy
/// decoding otherwise
final bool? doSample;

@override
HuggingFaceOptions copyWith(
{final String? model,
final int? concurrencyLimit,
final int? topK,
final double? topP,
final double? temperature,
final double? repetitionPenalty,
final int? maxNewTokens,
final double? maxTime,
final bool? returnFullText,
final int? numReturnSequences,
final bool? doSample}) {
return HuggingFaceOptions(
model: model ?? this.model,
repetitionPenalty: repetitionPenalty ?? this.repetitionPenalty,
returnFullText: returnFullText ?? this.returnFullText,
numReturnSequences: numReturnSequences ?? this.numReturnSequences,
doSample: doSample ?? this.doSample,
topK: topK ?? this.topK,
temperature: temperature ?? this.temperature,
topP: topP ?? this.topP,
maxTime: maxTime ?? this.maxTime,
maxNewTokens: maxNewTokens ?? this.maxNewTokens,
);
}
}

//inputs* string
// parameters object
// adapter_id string Lora adapter id
// best_of integer Generate best_of sequences and return the one if the highest token logprobs.
// decoder_input_details boolean Whether to return decoder input token logprobs and ids.
// details boolean Whether to return generation details.
// do_sample boolean Activate logits sampling.
// frequency_penalty number The parameter for frequency penalty. 1.0 means no penalty Penalize new tokens based on their existing frequency in the text so far, decreasing the model’s likelihood to repeat the same line verbatim.
// grammar unknown One of the following:
// (#1) object
// type* enum Possible values: json.
// value* unknown A string that represents a JSON Schema. JSON Schema is a declarative language that allows to annotate JSON documents with types and descriptions.
// (#2) object
// type* enum Possible values: regex.
// value* string
// max_new_tokens integer Maximum number of tokens to generate.
// repetition_penalty number The parameter for repetition penalty. 1.0 means no penalty. See this paper for more details.
// return_full_text boolean Whether to prepend the prompt to the generated text
// seed integer Random sampling seed.
// stop string[] Stop generating tokens if a member of stop is generated.
// temperature number The value used to module the logits distribution.
// top_k integer The number of highest probability vocabulary tokens to keep for top-k-filtering.
// top_n_tokens integer The number of highest probability vocabulary tokens to keep for top-n-filtering.
// top_p number Top-p value for nucleus sampling.
// truncate integer Truncate inputs tokens to the given size.
// typical_p number Typical Decoding mass See Typical Decoding for Natural Language Generation for more information.
// watermark boolean Watermarking with A Watermark for Large Language Models.
// stream
3 changes: 3 additions & 0 deletions packages/langchain_huggingface/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ topics:

environment:
sdk: ">=3.4.0 <4.0.0"
dependencies:
huggingface_client: ^1.5.0
langchain_core: ^0.3.6

0 comments on commit 072770e

Please sign in to comment.