Skip to content

Commit 0cb2d3d

Browse files
authored
Update SK example, fix bugs (#182)
1 parent 61ce5b3 commit 0cb2d3d

5 files changed

Lines changed: 80 additions & 23 deletions

File tree

examples/semantic-kernel/example.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55

66
import dotnet from 'node-api-dotnet';
77
import './bin/Microsoft.Extensions.Logging.Abstractions.js';
8+
import './bin/Microsoft.SemanticKernel.Abstractions.js';
89
import './bin/Microsoft.SemanticKernel.Core.js';
9-
import './bin/Microsoft.SemanticKernel.Functions.Semantic.js';
1010
import './bin/Microsoft.SemanticKernel.Connectors.AI.OpenAI.js';
11+
import './bin/Microsoft.SemanticKernel.TemplateEngine.Basic.js';
1112

1213
const Logging = dotnet.Microsoft.Extensions.Logging;
1314
const SK = dotnet.Microsoft.SemanticKernel;
@@ -27,16 +28,20 @@ const loggerFactory = {
2728
dispose() {}
2829
};
2930

31+
let kernelBuilder = new SK.KernelBuilder();
32+
kernelBuilder.WithLoggerFactory(loggerFactory);
33+
3034
// The JS marshaller does not yet support extension methods.
31-
const kernelBuilder = SK.OpenAIKernelBuilderExtensions.WithAzureChatCompletionService(
32-
SK.Kernel.Builder.WithLoggerFactory(loggerFactory),
35+
SK.OpenAIKernelBuilderExtensions.WithAzureOpenAIChatCompletionService(
36+
kernelBuilder,
3337
process.env['OPENAI_DEPLOYMENT'] || '',
3438
process.env['OPENAI_ENDPOINT'] || '',
3539
process.env['OPENAI_KEY'] || '',
3640
);
41+
3742
const kernel = kernelBuilder.Build();
3843

39-
const skPrompt = `{{$input}}
44+
const prompt = `{{$input}}
4045
4146
Give me the TLDR in 10 words.
4247
`;
@@ -52,11 +57,15 @@ such orders would conflict with the First Law.
5257
does not conflict with the First or Second Law.
5358
`;
5459

60+
const requestSettings = new SK.Connectors.AI.OpenAI.OpenAIRequestSettings();
61+
requestSettings.MaxTokens = 100;
62+
5563
// The JS marshaller does not yet support extension methods.
56-
const summaryFunction = SK.KernelSemanticFunctionExtensions
57-
.CreateSemanticFunction(kernel, skPrompt);
64+
const summaryFunction = SK.OpenAIKernelExtensions
65+
.CreateSemanticFunction(kernel, prompt, requestSettings);
5866

5967
const summary = await SK.SKFunctionExtensions.InvokeAsync(
6068
summaryFunction, textToSummarize, kernel);
6169

70+
console.log();
6271
console.log(summary.toString());

examples/semantic-kernel/semantic-kernel.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<PackageReference Include="Microsoft.SemanticKernel" Version="1.0.0-beta2" />
11+
<PackageReference Include="Microsoft.SemanticKernel" Version="1.0.0-beta8" />
1212
<PackageReference Include="Microsoft.JavaScript.NodeApi.Generator" Version="0.4.*-*" />
1313
</ItemGroup>
1414

src/NodeApi.DotNetHost/JSMarshaller.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,7 +2166,8 @@ private LambdaExpression BuildConvertToJSValueExpression(Type fromType)
21662166
Type[]? genericArguments = fromType.IsGenericType ?
21672167
fromType.GetGenericArguments() : null;
21682168

2169-
if (genericTypeDefinition == typeof(Memory<>))
2169+
if (genericTypeDefinition == typeof(Memory<>) ||
2170+
genericTypeDefinition == typeof(ReadOnlyMemory<>))
21702171
{
21712172
Type elementType = fromType.GenericTypeArguments[0];
21722173
if (!IsTypedArrayType(elementType))
@@ -2564,8 +2565,9 @@ private IEnumerable<Expression> BuildFromJSToStructExpressions(
25642565
foreach (PropertyInfo property in toType.GetProperties(
25652566
BindingFlags.Public | BindingFlags.Instance))
25662567
{
2567-
if (property.SetMethod == null)
2568+
if (property.SetMethod == null || property.SetMethod.GetParameters().Length > 1)
25682569
{
2570+
// Skip indexed properties, where the setter takes one or more parameters.
25692571
continue;
25702572
}
25712573

@@ -2616,6 +2618,12 @@ private IEnumerable<Expression> BuildToJSFromStructExpressions(
26162618
foreach (PropertyInfo property in fromType.GetProperties(
26172619
BindingFlags.Public | BindingFlags.Instance))
26182620
{
2621+
if (property.GetMethod == null || property.GetMethod.GetParameters().Length > 0)
2622+
{
2623+
// Skip indexed properties, where the getter takes one or more parameters.
2624+
continue;
2625+
}
2626+
26192627
Expression propertyName = Expression.Constant(ToCamelCase(property.Name));
26202628
yield return Expression.Assign(
26212629
Expression.Property(jsValueVariable, s_valueItem, propertyName),

src/NodeApi/Interop/JSCallbackOverload.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,12 @@ public static JSCallbackOverload Resolve(
169169
bool isMatch = true;
170170
for (int i = 0; i < argsCount; i++)
171171
{
172-
if (!IsArgumentTypeMatch(argTypes[i], overload.ParameterTypes[i]))
172+
Type parameterType = overload.ParameterTypes[i];
173+
isMatch = parameterType.IsArray ?
174+
argTypes[i] == JSValueType.Object && args[i].IsArray() :
175+
IsArgumentTypeMatch(argTypes[i], overload.ParameterTypes[i]);
176+
if (!isMatch)
173177
{
174-
isMatch = false;
175178
break;
176179
}
177180
}

src/NodeApi/JSTypedArray.cs

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,49 @@ public JSTypedArray(int length)
6565
/// </summary>
6666
public unsafe JSTypedArray(Memory<T> data)
6767
{
68-
// Check if this Memory is already owned by a JS TypedArray value.
68+
JSValue? value = GetJSValueForMemory(data);
69+
if (value is not null)
70+
{
71+
_value = value.Value;
72+
}
73+
else
74+
{
75+
// The Memory was NOT created from a JS TypedArray. Most likely it was allocated
76+
// directly or via a .NET array or string.
77+
78+
JSValue arrayBuffer = data.Length > 0 ?
79+
JSValue.CreateExternalArrayBuffer(data) : JSValue.CreateArrayBuffer(0);
80+
_value = JSValue.CreateTypedArray(ArrayType, data.Length, arrayBuffer, 0);
81+
}
82+
}
83+
84+
/// <summary>
85+
/// Creates a typed-array over read-memory, without copying. Only valid for memory
86+
/// which was previously marshalled from a JS typed-array to .NET.
87+
/// </summary>
88+
/// <exception cref="NotSupportedException">The memory is external to JS.</exception>
89+
public unsafe JSTypedArray(ReadOnlyMemory<T> data)
90+
{
91+
JSValue? value = GetJSValueForMemory(data);
92+
if (value is not null)
93+
{
94+
_value = value.Value;
95+
}
96+
else
97+
{
98+
// Consider copying the memory?
99+
throw new NotSupportedException(
100+
"Read-only memory cannot be transferred from .NET to JS.");
101+
}
102+
}
103+
104+
/// <summary>
105+
/// Checks if this Memory is already owned by a JS TypedArray value, and if so
106+
/// returns that JS value.
107+
/// </summary>
108+
/// <returns>The JS value, or null if the memory is external to JS.</returns>
109+
private static unsafe JSValue? GetJSValueForMemory(ReadOnlyMemory<T> data)
110+
{
69111
// This assumes the owner object of a Memory struct is stored as a reference in the
70112
// first (private) field of the struct. If the Memory internal structure ever changes
71113
// (in a future major version of the .NET Runtime), this unsafe code could crash.
@@ -83,24 +125,19 @@ public unsafe JSTypedArray(Memory<T> data)
83125
void* memoryLengthPointer = (byte*)memoryIndexPointer + Unsafe.SizeOf<int>();
84126
int length = Unsafe.Read<int>(memoryLengthPointer);
85127

86-
_value = manager.JSValue;
87-
int valueLength = _value.GetTypedArrayLength(out _);
128+
JSValue value = manager.JSValue;
129+
int valueLength = value.GetTypedArrayLength(out _);
88130

89131
if (index != 0 || length != valueLength)
90132
{
91133
// The Memory was sliced, so get an equivalent slice of the JS TypedArray.
92-
_value = _value.CallMethod("slice", index, index + length);
134+
value = value.CallMethod("slice", index, index + length);
93135
}
94-
}
95-
else
96-
{
97-
// The Memory was NOT created from a JS TypedArray. Most likely it was allocated
98-
// directly or via a .NET array or string.
99136

100-
JSValue arrayBuffer = data.Length > 0 ?
101-
JSValue.CreateExternalArrayBuffer(data) : JSValue.CreateArrayBuffer(0);
102-
_value = JSValue.CreateTypedArray(ArrayType, data.Length, arrayBuffer, 0);
137+
return value;
103138
}
139+
140+
return null;
104141
}
105142

106143
/// <summary>

0 commit comments

Comments
 (0)