Linq.AI.OpenAI
3.1.0
dotnet add package Linq.AI.OpenAI --version 3.1.0
NuGet\Install-Package Linq.AI.OpenAI -Version 3.1.0
<PackageReference Include="Linq.AI.OpenAI" Version="3.1.0" />
<PackageVersion Include="Linq.AI.OpenAI" Version="3.1.0" />
<PackageReference Include="Linq.AI.OpenAI" />
paket add Linq.AI.OpenAI --version 3.1.0
#r "nuget: Linq.AI.OpenAI, 3.1.0"
#addin nuget:?package=Linq.AI.OpenAI&version=3.1.0
#tool nuget:?package=Linq.AI.OpenAI&version=3.1.0
Linq.AI.OpenAI
This library implements a Linq.AI ITransformer for the OpenAI API. These extensions make it easy to manipulate collections of data using LLM AI models.
Installation
dotnet add package Linq.AI.OpenAI
ITransformer
The Linq.AI package needs an ITransformer for the AI model that is being used.
You instantiate a transformer like this:
var model = new OpenAITransformer(model: "gpt-4o-mini", new ApiKeyCredential("<openai.apikey>"));
NOTE: The model must support structured output.
Model Methods
The model methods make it easy work to use natural language to process a single item (aka text, object, etc.).
Extension | Description |
---|---|
.ClassifyAsync() | classify the text using a model. |
.SummarizeAsync() | Create a summarization for the text by using a model. |
.MatchesAsync() | Return whether the text matches using a model. |
.QueryAsync() | get the answer to a global question using a model. |
.QueryAboutAsync() | get the answer to a question from the text using a model. |
.ExtractAsync() | Extract items from the text using a model. |
.CompareAsync() | Compare 2 objects for semantic equivelancy |
model.ClassifyAsync()
Classify an item using an enumeration or list of categories.
enum Genres { Rock, Pop, Electronica, Country, Classical };
var classification = await model.ClassifyAsync<Genres>(item);
You can use a collection of strings as categories as well.
var classification = await model.ClassifyAsync<string>(item, new [] {"Rock","Pop","Electronica","Country","Classical"});
model.SummarizeAsync()
Summarize the item
var summary = await model.SummarizeAsync(item, "with 3 words");
model.MatchesAsync()
Get true/false if the item matches the question
if (await model.MatchesAsync(item, "there is date"))
...
model.QueryAsync()
Ask a question using models knowledge.
var answer = await model.QueryAsync("what is the birthday of barack obama?");
Query can take a typed output
var date = await model.QueryAsync<int>("what is the day of the month for the birthday of barack obama?");
model.QueryAboutAsync()
Ask a question about an item
var answer = await model.QueryAboutAsync(item, "what is his birthday?");
It also can take a typed output
var date = await model.QueryAboutAsync<int>(person, "how tall is he in inches?");
model.ExtractAsync()
Extracts a collection of items from the item.
Example using model to select text from the item
var words = await model.ExtractAsync<string>(item, "The second word of every paragraph");
You can use the model to select structured data.
public class HREF
{
public string Url {get;set;}
public string Title {get;set;}
}
var hrefs = await model.ExtractAsync<HREF>(item).ToListAsync();
model.Compare()
Compares two objects for semantic equivelancy.
Assert.IsTrue(await Model.CompareAsync("fourteen", "14"));
Assert.IsTrue(await Model.CompareAsync("fourteen years old", "10 + 4 years"));
Assert.IsTrue(await Model.CompareAsync("Me llamo Tom", "Mi nombre es Tom"));
Assert.IsTrue(await Model.CompareAsync("My name is Tom", "Mi nombre es Tom", instructions: "allow different langauges to be semantically equal"));
Assert.IsFalse(await Model.CompareAsync("Me llamo Tom", "Mi padre es Tom"));
Assert.IsTrue(await Model.CompareAsync(
new
{
Introduction = "My name is Tom",
Background="I live in Kirkland, Washington"
},
new
{
Introduction = "I'm Tom",
Background = "I'm from Kirkland, Washington"
}));
Linq Extensions
The object extensions use the ITransformer model to work each item in a collections.
Extension | Description |
---|---|
.SelectAsync() | Transforms each item into another format with natural language. |
.WhereAsync() | Keeps each item which matches with natural language filter. |
.ClassifyAsync() | Classify each item. |
.SummarizeAsync() | Create a summarization for each item. |
.QueryAboutEachAsync() | Gets the question to a question about each item. |
enumerable.SelectAsync()
.SelectAsync() let's you transform the source into target using an ITransformer model.
You can use it to transform an object from one format to another by simply giving the types. The model will use AI to appropriately map the properties between the object types.
var targetItems = await items.SelectAsync<SourceItem,TargetItem>(model).ToListAsync();
Transform a collection of text into another format, like markdown.
var markdownItems = awit items.SelectAsync(model, goal: """"
transform each item into markdown like this:
# {{TITLE}}
{{AUTHOR}}
{{DESCRIPTION}}
""");
enumerable.WhereAsync()
Filter a collection using natural language
var smallItems = await items.WhereAsync(model, "item would fit in a bread box");
enumerable.ClassifyAsync()
This allows you to classify each item using a model;
enum Genres { Rock, Pop, Electronica, Country, Classical };
var classifiedItems = await items.ClassifyAsync<Genres>(model);
enumerable.SummarizeAsync()
Generate text summary for each item using an ITransformer model.
var summaries = await items.SummarizeAsync(model);
You can control the summarization with a hint
var summaries = await items.SummarizeAsync(model, "generate a 3 word summary");
enumerable.QueryAboutEach()
This operator let's you ask a question for each item in a collection.
var answers = await items.QueryAboutEachAsync<float>(model, "What is the cost?");
Linq.AI and Vision
You can use Linq.AI and the model to work with images.
Simply pass a Uri() to an image or a ChatMessageContentPart for the image and you can call any of the extension methods.
Examples:
var uri = new Uri("https://2cupsoftravel.com/wp-content/uploads/2022/10/Oktoberfest-munich-things-to-know.jpg");
var uri2 = new Uri("https://2cupsoftravel.com/wp-content/uploads/2022/10/20220928_115250-1200x900.jpg");
// summarize an image uri
var summmary = await Model.SummarizeAsync(uri);
// ask a question about a group of image uris
var matches = await Model.MatchesAsync(new [] { uri, uri2 }, "Are these pictures of people drinking beer?");
// extract text out of an image uri.
var text = await Model.SelectAsync<string>(uri, "Extract all phrases from the image");
// upload and classify an image binary
var imagePart = ChatMessageContentPart.CreateImagePart(BinaryData.FromBytes(imageBytes), "image/jpeg");
var classification = await Model.ClassifyAsync<Mood>(imagePart);
Adding Tools
Linq.AI makes it super easy to add tools (aka functions) to your OpenAI model.
There are 2 ways to do it:
- Define a static class with static methods on it
- Create a Delegate
If the model decides it needs the result of your function Liqn.AI will automatically invoke the function doing all of the type wrangling needed and then pass the result back to the model to use to create the final answer.
NOTE: Delegates can be synchronous or async.
public static class MyFunctions
{
[Description("Perform PowPow calculation")]
public static double PowPow( [Description("first number")][Required] double x,
[Description("second number")][Required] double y)
{
return Math.Pow(x,y);
}
}
var model = new new OpenAITransformer(model: "gpt-4o-mini", "<open ai key>")
.AddTools<MyFunctions>()
.AddTool("Sum", "Add 2 numbers",
([Description("the first number to add") int x,
[Description("the second number to add") int y)
{
return x+y;
})
.AddTool("LookupAlbumCover", "Lookup up a record album covere",
async ([Description("the album name") string name, CancellationToken ct) =>
{
await Task.Delay(1000);
return result;
});
Now if query needs the result of the function it will just work
await model.GenerateAsync<double>("What's the powpow for 3 and 4?");
InstructionAttribute
You can add [Description] or [Instruction] attributes to properties on you classes to help the LLM properly work with your objects when the property name is amibiguious.
public class LeaderInfo
{
[Instruction("The name of country that the person is leader for")]
public string Name {get;set;}
[Instruction("The title for the leadership role the leader has. (Example: President)")]
public string Title {get;set;}
[Instruction("The full name for the leader")]
public string FullName {get;set;}
[Instruction("The year they took the role.")]
public int? Date { get; set;}
}
var leader = await model.QueryAsync<LeaderInfo>("barack obama");
// {"Name":"United States","Title":"President","FullName":"Barack Hussein Obama II","Date":2009}
This library was heaviy inspired by stevenic's agentm-js library, Kudos!
Changes
V3
- Made all methods Async
- Added IAsyncEnumerable support
- Removed parallel processing, you should use Plinq.NET directly
V1, V2
- Basic library using parallel internal and non-async processing.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
.NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Linq.AI (>= 3.1.0)
- OpenAI (>= 2.2.0-beta.4)
- System.Linq.Async (>= 6.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
3.1.0 | 67 | 25 days ago |
3.0.1 | 116 | a month ago |
3.0.0 | 123 | a month ago |
2.2.1 | 87 | 6 months ago |
2.2.0 | 80 | 8 months ago |
2.1.0 | 74 | 8 months ago |
2.0.6 | 108 | 9 months ago |
2.0.5 | 84 | 9 months ago |
2.0.4 | 111 | 9 months ago |
2.0.3 | 71 | 9 months ago |
2.0.2 | 75 | 9 months ago |
2.0.1 | 85 | 9 months ago |
1.3.0 | 76 | 9 months ago |
1.2.3 | 75 | 9 months ago |
1.2.2 | 75 | 9 months ago |
1.2.1 | 84 | 9 months ago |
1.2.0 | 78 | 9 months ago |
1.1.0 | 83 | 9 months ago |
1.0.1 | 76 | 9 months ago |
1.0.0 | 78 | 9 months ago |