diff --git a/src/LLTSharp/ITemplate.cs b/src/LLTSharp/ITemplate.cs
index 768bfb2..d0ad4e5 100644
--- a/src/LLTSharp/ITemplate.cs
+++ b/src/LLTSharp/ITemplate.cs
@@ -1,13 +1,10 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
+using System.Collections.Generic;
using LLTSharp.Metadata;
-using Microsoft.Extensions.AI;
namespace LLTSharp
{
///
- /// Interface for a template that can be used to generate prompts.
+ /// Interface for a template that can be used to generate contents.
///
public interface ITemplate
{
@@ -25,7 +22,7 @@ public interface ITemplate
}
///
- /// Interface for a template that can be used to generate prompts.
+ /// Interface for a template that can be used to generate content.
///
/// The type of result produced by the template.
public interface ITemplate : ITemplate
@@ -35,16 +32,16 @@ public interface ITemplate : ITemplate
}
///
- /// Represents a prompt template that produces a string result.
+ /// Represents a text template that produces a string result.
///
- public interface IPromptTemplate : ITemplate
+ public interface ITextTemplate : ITemplate
{
}
///
/// Represents a messages template that produces a collection of messages.
///
- public interface IMessagesTemplate : ITemplate>
+ public interface IMessagesTemplate : ITemplate>
{
}
}
\ No newline at end of file
diff --git a/src/LLTSharp/LLTParser.cs b/src/LLTSharp/LLTParser.cs
index dc70b22..68f45d3 100644
--- a/src/LLTSharp/LLTParser.cs
+++ b/src/LLTSharp/LLTParser.cs
@@ -86,14 +86,14 @@ private static void DeclareValues(ParserBuilder builder)
builder.CreateRule("constant_array")
.Literal("[")
.ZeroOrMoreSeparated(b => b.Rule("constant"), b => b.Literal(","), allowTrailingSeparator: true)
- .ConfigureLast(c => c.SkippingStrategy(ParserSkippingStrategy.SkipBeforeParsingGreedy))
+ .ConfigureLast(c => c.Skip(b => b.Rule("skip"), ParserSkippingStrategy.SkipBeforeParsingGreedy))
.Literal("]")
.Transform(v => new TemplateArrayAccessor(v.Children[1].SelectValues()));
builder.CreateRule("constant_object")
.Literal("{")
.ZeroOrMoreSeparated(b => b.Rule("constant_pair"), b => b.Literal(","), allowTrailingSeparator: true)
- .ConfigureLast(c => c.SkippingStrategy(ParserSkippingStrategy.SkipBeforeParsingGreedy))
+ .ConfigureLast(c => c.Skip(b => b.Rule("skip"), ParserSkippingStrategy.SkipBeforeParsingGreedy))
.Literal("}")
.Transform(v =>
{
@@ -526,18 +526,39 @@ private static void DeclareTextTemplates(ParserBuilder builder)
node.Refine(depth: 1);
var library = v.GetParsingParameter().LocalLibrary;
- var template = new PromptTemplate(node, new MetadataCollection(metadata), library);
+ var template = new TextTemplate(node, new MetadataCollection(metadata), library);
library.Add(template);
return template;
});
+ var textEscapes = new Dictionary
+ {
+ ["@@"] = "@",
+ ["{{"] = "{",
+ ["}}"] = "}"
+ };
+
+ var textForbidden = new string[]
+ {
+ "@", "{", "}", "`````"
+ };
+
builder.CreateRule("text_content")
- .EscapedTextDoubleChars("@{}", allowsEmpty: false)
+ .EscapedText(textEscapes, textForbidden, allowsEmpty: false)
+ .Transform(v => new TextTemplatePlainTextNode(v.GetIntermediateValue()));
+
+ builder.CreateRule("text_multiline_content")
+ .Token(b => b.Between(
+ b => b.Literal("`````"),
+ b => b.TextUntil("`````"),
+ b => b.Literal("`````")
+ ))
.Transform(v => new TextTemplatePlainTextNode(v.GetIntermediateValue()));
builder.CreateRule("text_statements")
.ZeroOrMore(b => b.Choice(
c => c.Rule("text_content"),
+ c => c.Rule("text_multiline_content"),
c => c.Rule("text_statement")))
.Transform(v =>
{
@@ -567,7 +588,7 @@ private static void DeclareTextTemplates(ParserBuilder builder)
)
.Transform(v => v.GetValue(1));
- builder.CreateRule("text_expression_inner")
+ builder.CreateRule("text_expression")
.Rule("simple_expression") // We don't want to use binary expressions in text statements
.Optional(b => b
.Literal(':')
@@ -578,21 +599,6 @@ private static void DeclareTextTemplates(ParserBuilder builder)
return new TextTemplateExpressionNode(v.GetValue(0), format);
});
- builder.CreateRule("text_expression")
- .Custom(
- (self, ctx, sett, childSett, children, childrenIds) =>
- {
- var result = self.ParseRule(childrenIds[0], ctx, childSett);
- if (!result.success)
- return result;
- var modifierChild = result.children[1];
- if (modifierChild.length == 0)
- result.length = result.children[0].length;
- return result;
- },
- b => b.Rule("text_expression_inner")
- );
-
builder.CreateRule("text_if")
.Keyword("if")
.Rule("expression")
@@ -729,15 +735,18 @@ static LLTParser()
{
var builder = new ParserBuilder();
- // Settings //
- builder.Settings
- .Skip(s => s.Choice(
+ // Skip rule //
+ builder.CreateRule("skip")
+ .Choice(
c => c.Whitespaces(),
c => c.Literal("@/").TextUntil('\n', '\r'), // @/ C#-like comments
c => c.Literal("@*").TextUntil("*@").Literal("*@")) // @*...*@ comments
- .ConfigureForSkip(), // Ignore all errors when parsing comments and unnecessary whitespace
- ParserSkippingStrategy.TryParseThenSkipLazy) // Allows rules to capture skip-rules contents if can, such as whitespaces
- .UseCaching().RecordWalkTrace(); // If caching is disabled, prepare to wait for a long time (seconds) when encountering an error :P (you will also get a million of errors, seriously)
+ .ConfigureForSkip(); // Ignore all errors when parsing comments and unnecessary whitespace
+
+ // Settings //
+ builder.Settings
+ .Skip(b => b.Rule("skip"), ParserSkippingStrategy.TryParseThenSkipLazy) // Allows rules to capture skip-rules contents if can, such as whitespaces
+ .UseCaching(); // If caching is disabled, prepare to wait for a long time (seconds) when encountering an error :P (you will also get a million of errors, seriously)
// ---- Values ---- //
DeclareValues(builder);
diff --git a/src/LLTSharp/LLTSharp.csproj b/src/LLTSharp/LLTSharp.csproj
index 3152ca0..672e164 100644
--- a/src/LLTSharp/LLTSharp.csproj
+++ b/src/LLTSharp/LLTSharp.csproj
@@ -8,11 +8,11 @@
LLTSharp
- 1.1.0
+ 1.2.0
Roman K.
RomeCore
LLTSharp
- A lightweight .NET template engine for LLM with messages and prompt templates support.
+ A lightweight .NET template engine for LLM with messages and text templates support.
README.md
template, llm, template-engine, language-models
https://github.com/RomeCore/LLTSharp
@@ -25,8 +25,7 @@
-
-
+
\ No newline at end of file
diff --git a/src/LLTSharp/Message.cs b/src/LLTSharp/Message.cs
new file mode 100644
index 0000000..28e72ec
--- /dev/null
+++ b/src/LLTSharp/Message.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace LLTSharp
+{
+ ///
+ /// Represents a role in a conversation.
+ ///
+ public enum Role
+ {
+ ///
+ /// System role, typically used for system instructions or context.
+ ///
+ System,
+
+ ///
+ /// User role, typically used for user input or questions.
+ ///
+ User,
+
+ ///
+ /// Assistant role, typically used for responses or actions.
+ ///
+ Assistant,
+
+ ///
+ /// Tool role, typically used for responses from tool calls.
+ ///
+ Tool
+ }
+
+ ///
+ /// Represents a single message in a conversation with LLM.
+ ///
+ public class Message
+ {
+ ///
+ /// Gets or sets the role of the message sender. Typically "user" or "assistant".
+ ///
+ public Role Role { get; }
+
+ ///
+ /// Gets or sets the content of the message.
+ ///
+ public string Content { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Message()
+ {
+ Role = Role.System;
+ Content = string.Empty;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The role of the message sender.
+ /// The content of the message.
+ public Message(Role role, string content)
+ {
+ Role = role;
+ Content = content;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LLTSharp/MessagesTemplate.cs b/src/LLTSharp/MessagesTemplate.cs
index 697ca4a..f038c6e 100644
--- a/src/LLTSharp/MessagesTemplate.cs
+++ b/src/LLTSharp/MessagesTemplate.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Text;
using LLTSharp.Metadata;
-using Microsoft.Extensions.AI;
namespace LLTSharp
{
@@ -39,7 +38,7 @@ public MessagesTemplate(MessagesTemplateNode mainNode, IMetadataCollection metad
///
/// The context accessor to use for rendering.
/// The rendered prompt as a collection of messages.
- public IEnumerable Render(object? context = null)
+ public IEnumerable Render(object? context = null)
{
var ctx = new TemplateContextAccessor(TemplateDataAccessor.Create(context), Metadata, library: LocalLibrary);
return _node.Render(ctx);
diff --git a/src/LLTSharp/MessagesTemplateNode.cs b/src/LLTSharp/MessagesTemplateNode.cs
index 45e7807..325cf3e 100644
--- a/src/LLTSharp/MessagesTemplateNode.cs
+++ b/src/LLTSharp/MessagesTemplateNode.cs
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Text;
-using Microsoft.Extensions.AI;
namespace LLTSharp
{
@@ -15,7 +13,7 @@ public abstract class MessagesTemplateNode
///
/// The context accessor containing the data to render.
/// A collection of messages representing the rendered template node.
- public abstract IEnumerable Render(TemplateContextAccessor context);
+ public abstract IEnumerable Render(TemplateContextAccessor context);
///
/// Refines the template after parsing an AST to remove indents and unnecessary leading/trailing whitespaces.
diff --git a/src/LLTSharp/TemplateContextAccessor.cs b/src/LLTSharp/TemplateContextAccessor.cs
index 7552287..dc9110c 100644
--- a/src/LLTSharp/TemplateContextAccessor.cs
+++ b/src/LLTSharp/TemplateContextAccessor.cs
@@ -5,7 +5,6 @@
using System.Text;
using LLTSharp.DataAccessors;
using LLTSharp.Metadata;
-using Microsoft.Extensions.AI;
namespace LLTSharp
{
@@ -223,7 +222,7 @@ public string RenderTemplate(string identifier, TemplateDataAccessor? newContext
if (template == null)
throw new TemplateRuntimeException($"Template '{identifier}' not found.");
- if (template is not PromptTemplate && template is not PlaintextTemplate)
+ if (template is not TextTemplate && template is not PlaintextTemplate)
throw new TemplateRuntimeException($"Template '{identifier}' is not a text template.");
var context = newContext ?? this;
@@ -239,7 +238,7 @@ public string RenderTemplate(string identifier, TemplateDataAccessor? newContext
/// The identifier of the messages template to render.
/// The new context to use for rendering the template. If null, uses the current context.
/// The rendered template as a collection of messages.
- public IEnumerable RenderMessagesTemplate(string identifier, TemplateDataAccessor? newContext)
+ public IEnumerable RenderMessagesTemplate(string identifier, TemplateDataAccessor? newContext)
{
var template = Library.TryRetrieve(identifier);
if (template == null)
diff --git a/src/LLTSharp/TemplateNodes/MessagesTemplateEntryNode.cs b/src/LLTSharp/TemplateNodes/MessagesTemplateEntryNode.cs
index 59ba242..496f4ce 100644
--- a/src/LLTSharp/TemplateNodes/MessagesTemplateEntryNode.cs
+++ b/src/LLTSharp/TemplateNodes/MessagesTemplateEntryNode.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
-using Microsoft.Extensions.AI;
namespace LLTSharp.TemplateNodes
{
@@ -32,21 +31,21 @@ public MessagesTemplateEntryNode(TemplateExpressionNode role, TextTemplateNode c
Child = child ?? throw new ArgumentNullException(nameof(child));
}
- public override IEnumerable Render(TemplateContextAccessor context)
+ public override IEnumerable Render(TemplateContextAccessor context)
{
var role = Role.Evaluate(context);
var content = Child.Render(context);
- ChatMessage message = role.ToString() switch
+ Message message = role.ToString() switch
{
- "system" => new ChatMessage(ChatRole.System, content),
- "user" => new ChatMessage(ChatRole.User, content),
- "assistant" => new ChatMessage(ChatRole.Assistant, content),
+ "system" => new Message(LLTSharp.Role.System, content),
+ "user" => new Message(LLTSharp.Role.User, content),
+ "assistant" => new Message(LLTSharp.Role.Assistant, content),
// "tool" => new ToolMessage(content), // TODO: Add support for tool call ids and tool names
"tool" => throw new TemplateRuntimeException($"Tool messages are not yet supported.", dataAccessor: context, messagesTemplateNode: this),
_ => throw new TemplateRuntimeException($"Invalid role '{role}'.", dataAccessor: context, messagesTemplateNode: this),
};
- return new ChatMessage[] { message };
+ return new Message[] { message };
}
public override void Refine(int depth)
diff --git a/src/LLTSharp/TemplateNodes/MessagesTemplateForeachNode.cs b/src/LLTSharp/TemplateNodes/MessagesTemplateForeachNode.cs
index b07ecea..909acee 100644
--- a/src/LLTSharp/TemplateNodes/MessagesTemplateForeachNode.cs
+++ b/src/LLTSharp/TemplateNodes/MessagesTemplateForeachNode.cs
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
-using System.Text;
using LLTSharp.DataAccessors;
-using Microsoft.Extensions.AI;
namespace LLTSharp.TemplateNodes
{
@@ -41,7 +39,7 @@ public MessagesTemplateForeachNode(TemplateExpressionNode source, MessagesTempla
IterableName = string.IsNullOrEmpty(iterableName) ? throw new ArgumentException("The iterable name cannot be null or empty.", nameof(iterableName)) : iterableName;
}
- public override IEnumerable Render(TemplateContextAccessor context)
+ public override IEnumerable Render(TemplateContextAccessor context)
{
var source = Source.Evaluate(context);
@@ -49,7 +47,7 @@ public override IEnumerable Render(TemplateContextAccessor context)
throw new TemplateRuntimeException($"The source expression does not provide an enumerable data source.",
dataAccessor: context, expressionNode: Source);
- List messages = new List();
+ List messages = new List();
context.PushFrame();
foreach (var item in enumerableSource)
diff --git a/src/LLTSharp/TemplateNodes/MessagesTemplateIfElseNode.cs b/src/LLTSharp/TemplateNodes/MessagesTemplateIfElseNode.cs
index c2571dd..8802936 100644
--- a/src/LLTSharp/TemplateNodes/MessagesTemplateIfElseNode.cs
+++ b/src/LLTSharp/TemplateNodes/MessagesTemplateIfElseNode.cs
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using Microsoft.Extensions.AI;
namespace LLTSharp.TemplateNodes
{
@@ -40,9 +38,9 @@ public MessagesTemplateIfElseNode(TemplateExpressionNode condition, MessagesTemp
ElseBranch = elseBranch;
}
- public override IEnumerable Render(TemplateContextAccessor context)
+ public override IEnumerable Render(TemplateContextAccessor context)
{
- IEnumerable? result = null;
+ IEnumerable? result = null;
var conditionResult = Condition.Evaluate(context);
@@ -55,7 +53,7 @@ public override IEnumerable Render(TemplateContextAccessor context)
context.PopFrame();
- return result ?? Enumerable.Empty();
+ return result ?? Enumerable.Empty();
}
public override void Refine(int depth)
diff --git a/src/LLTSharp/TemplateNodes/MessagesTemplateRenderNode.cs b/src/LLTSharp/TemplateNodes/MessagesTemplateRenderNode.cs
index e08b712..923db61 100644
--- a/src/LLTSharp/TemplateNodes/MessagesTemplateRenderNode.cs
+++ b/src/LLTSharp/TemplateNodes/MessagesTemplateRenderNode.cs
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Text;
-using Microsoft.Extensions.AI;
namespace LLTSharp.TemplateNodes
{
@@ -31,7 +29,7 @@ public MessagesTemplateRenderNode(TemplateExpressionNode name, TemplateExpressio
Context = context;
}
- public override IEnumerable Render(TemplateContextAccessor context)
+ public override IEnumerable Render(TemplateContextAccessor context)
{
var templateName = Name.Evaluate(context).ToString(); // Evaluate the expression to get the template name
var newContext = Context?.Evaluate(context);
diff --git a/src/LLTSharp/TemplateNodes/MessagesTemplateSequentialNode.cs b/src/LLTSharp/TemplateNodes/MessagesTemplateSequentialNode.cs
index f7703a5..f730e00 100644
--- a/src/LLTSharp/TemplateNodes/MessagesTemplateSequentialNode.cs
+++ b/src/LLTSharp/TemplateNodes/MessagesTemplateSequentialNode.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
-using Microsoft.Extensions.AI;
namespace LLTSharp.TemplateNodes
{
@@ -26,9 +25,9 @@ public MessagesTemplateSequentialNode(IEnumerable children
Children = children?.ToArray() ?? throw new ArgumentNullException(nameof(children));
}
- public override IEnumerable Render(TemplateContextAccessor context)
+ public override IEnumerable Render(TemplateContextAccessor context)
{
- List messages = new List();
+ List messages = new List();
foreach (var child in Children)
{
messages.AddRange(child.Render(context));
diff --git a/src/LLTSharp/TemplateNodes/MessagesTemplateVariableAssignNode.cs b/src/LLTSharp/TemplateNodes/MessagesTemplateVariableAssignNode.cs
index a331584..4649851 100644
--- a/src/LLTSharp/TemplateNodes/MessagesTemplateVariableAssignNode.cs
+++ b/src/LLTSharp/TemplateNodes/MessagesTemplateVariableAssignNode.cs
@@ -1,8 +1,6 @@
using System;
using System.Linq;
using System.Collections.Generic;
-using System.Text;
-using Microsoft.Extensions.AI;
namespace LLTSharp.TemplateNodes
{
@@ -39,13 +37,13 @@ public MessagesTemplateVariableAssignNode(string variableName, TemplateExpressio
AssignsToExisting = assignsToExisting;
}
- public override IEnumerable Render(TemplateContextAccessor context)
+ public override IEnumerable Render(TemplateContextAccessor context)
{
if (AssignsToExisting)
context.AssignVariable(VariableName, Expression.Evaluate(context));
else
context.SetVariable(VariableName, Expression.Evaluate(context));
- return Enumerable.Empty();
+ return Enumerable.Empty();
}
}
}
\ No newline at end of file
diff --git a/src/LLTSharp/TemplateNodes/MessagesTemplateWhileNode.cs b/src/LLTSharp/TemplateNodes/MessagesTemplateWhileNode.cs
index ba0634d..263e9d1 100644
--- a/src/LLTSharp/TemplateNodes/MessagesTemplateWhileNode.cs
+++ b/src/LLTSharp/TemplateNodes/MessagesTemplateWhileNode.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using Microsoft.Extensions.AI;
namespace LLTSharp.TemplateNodes
{
@@ -28,9 +27,9 @@ public MessagesTemplateWhileNode(TemplateExpressionNode condition, MessagesTempl
Child = child ?? throw new ArgumentNullException(nameof(child));
}
- public override IEnumerable Render(TemplateContextAccessor context)
+ public override IEnumerable Render(TemplateContextAccessor context)
{
- List messages = new List();
+ List messages = new List();
context.PushFrame();
try
diff --git a/src/LLTSharp/TemplateNodes/TextTemplateForeachNode.cs b/src/LLTSharp/TemplateNodes/TextTemplateForeachNode.cs
index d86e971..35c97c4 100644
--- a/src/LLTSharp/TemplateNodes/TextTemplateForeachNode.cs
+++ b/src/LLTSharp/TemplateNodes/TextTemplateForeachNode.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Text;
using LLTSharp.DataAccessors;
-using Microsoft.Extensions.AI;
namespace LLTSharp.TemplateNodes
{
diff --git a/src/LLTSharp/PromptTemplate.cs b/src/LLTSharp/TextTemplate.cs
similarity index 78%
rename from src/LLTSharp/PromptTemplate.cs
rename to src/LLTSharp/TextTemplate.cs
index 7090421..87f8393 100644
--- a/src/LLTSharp/PromptTemplate.cs
+++ b/src/LLTSharp/TextTemplate.cs
@@ -8,9 +8,9 @@
namespace LLTSharp
{
///
- /// Represents a prompt template for generating prompts.
+ /// Represents a text template for generating strings.
///
- public class PromptTemplate : ITemplate
+ public class TextTemplate : ITextTemplate
{
private readonly TextTemplateNode _node;
@@ -22,13 +22,13 @@ public class PromptTemplate : ITemplate
public TemplateLibrary LocalLibrary { get; }
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The main node of the template.
/// The metadata associated with this template.
/// The local library associated with this prompt template.
///
- public PromptTemplate(TextTemplateNode mainNode, IMetadataCollection metadata, TemplateLibrary localLibrary)
+ public TextTemplate(TextTemplateNode mainNode, IMetadataCollection metadata, TemplateLibrary localLibrary)
{
_node = mainNode ?? throw new ArgumentNullException(nameof(mainNode));
Metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
@@ -36,10 +36,10 @@ public PromptTemplate(TextTemplateNode mainNode, IMetadataCollection metadata, T
}
///
- /// Renders the prompt template using the provided data accessor.
+ /// Renders the text template using the provided data accessor.
///
/// The context accessor to use for rendering.
- /// The rendered prompt as a string.
+ /// The rendered text as a string.
public string Render(object? context = null)
{
var ctx = new TemplateContextAccessor(TemplateDataAccessor.Create(context), Metadata, library: LocalLibrary);
diff --git a/tests/LLTSharp.Tests/TemplateFormattingTests.cs b/tests/LLTSharp.Tests/TemplateFormattingTests.cs
index 9f17f55..6b9c218 100644
--- a/tests/LLTSharp.Tests/TemplateFormattingTests.cs
+++ b/tests/LLTSharp.Tests/TemplateFormattingTests.cs
@@ -3,7 +3,6 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using Microsoft.Extensions.AI;
namespace LLTSharp.Tests
{
@@ -63,6 +62,77 @@ Have a nice day.
Assert.Equal(expectedYoung, renderedYoung);
}
+ [Fact]
+ public void IfElseWithMultilineFormatting()
+ {
+ var parser = new LLTParser();
+
+ var templateStr =
+ """
+ @template if_else_format
+ {
+ Greetings, @name!
+ @if code_type == 'csharp'
+ {
+ `````
+ class Program
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Hello, world, @user!");
+ }
+ }
+ `````
+ }
+ else if code_type == 'python'
+ {
+
+ `````
+ if __name__ == "main":
+ print("Hello, world, @user!")
+ `````
+ }
+
+ Have a nice day.
+ }
+ """;
+
+ var template = parser.Parse(templateStr).First();
+
+ var dataCsharp = new { name = "Andrew", code_type = "csharp" };
+ var dataPython = new { name = "Alice", code_type = "python" };
+
+ var renderedCsharp = template.Render(dataCsharp).ToString();
+ var renderedPython = template.Render(dataPython).ToString();
+
+ var expectedCsharp =
+ """
+ Greetings, Andrew!
+ class Program
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Hello, world, @user!");
+ }
+ }
+
+ Have a nice day.
+ """;
+
+ var expectedPython =
+ """
+ Greetings, Alice!
+
+ if __name__ == "main":
+ print("Hello, world, @user!")
+
+ Have a nice day.
+ """;
+
+ Assert.Equal(expectedCsharp, renderedCsharp);
+ Assert.Equal(expectedPython, renderedPython);
+ }
+
[Fact]
public void ForeachTemplateFormatting()
{
@@ -458,7 +528,7 @@ @foreach name in names
instructions = new[] { "Do this", "Do that" }
};
- var messages = (IEnumerable)template.Render(context);
+ var messages = (IEnumerable)template.Render(context);
var system = messages.ElementAt(0);
var user1 = messages.ElementAt(1);
@@ -474,12 +544,12 @@ You are a helpful assistant.
Instruction 2: Do that
""";
- Assert.Equal(ChatRole.System, system.Role);
- Assert.Equal(expectedSystemContent, system.Text);
- Assert.Equal(ChatRole.User, user1.Role);
- Assert.Equal("Hello, i am Alex!", user1.Text);
- Assert.Equal("Hello, i am Rob!", user2.Text);
- Assert.Equal("Hello, i am John!", user3.Text);
+ Assert.Equal(Role.System, system.Role);
+ Assert.Equal(expectedSystemContent, system.Content);
+ Assert.Equal(Role.User, user1.Role);
+ Assert.Equal("Hello, i am Alex!", user1.Content);
+ Assert.Equal("Hello, i am Rob!", user2.Content);
+ Assert.Equal("Hello, i am John!", user3.Content);
}
}
}
\ No newline at end of file
diff --git a/tests/LLTSharp.Tests/TemplateRenderingTests.cs b/tests/LLTSharp.Tests/TemplateRenderingTests.cs
index c340484..e7373e2 100644
--- a/tests/LLTSharp.Tests/TemplateRenderingTests.cs
+++ b/tests/LLTSharp.Tests/TemplateRenderingTests.cs
@@ -4,7 +4,6 @@
using System.Text;
using System.Threading.Tasks;
using LLTSharp.Metadata;
-using Microsoft.Extensions.AI;
namespace LLTSharp.Tests
{
@@ -182,15 +181,15 @@ You are a helpful assistant.
var template = parser.Parse(templateStr).First();
var context = new { name = "Alex" };
- var messages = (IEnumerable)template.Render(context);
+ var messages = (IEnumerable)template.Render(context);
var system = messages.ElementAt(0);
var user = messages.ElementAt(1);
- Assert.Equal(ChatRole.System, system.Role);
- Assert.Contains("You are a helpful assistant.", system.Text);
- Assert.Equal(ChatRole.User, user.Role);
- Assert.Contains("Hello, i am Alex!", user.Text);
+ Assert.Equal(Role.System, system.Role);
+ Assert.Contains("You are a helpful assistant.", system.Content);
+ Assert.Equal(Role.User, user.Role);
+ Assert.Contains("Hello, i am Alex!", user.Content);
}
}
}
\ No newline at end of file