Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion examples/appSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"ApiKey": "?",
"Model": "gpt-35-turbo"
},
// Custom. Load Config by this name
// Custom. Load Open AI Config using this name
"OpenAI_GPT4": {
"Azure": true,
"Endpoint": "?",
Expand Down
4 changes: 3 additions & 1 deletion src/typechat.dialog/Agent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
namespace Microsoft.TypeChat.Dialog;

/// <summary>
/// A multi-turn message passing Agent
/// Experimental:
/// A multi-turn message passing Agent that returns strongly typed responses
/// Message
/// </summary>
public class Agent<T>
{
Expand Down
49 changes: 16 additions & 33 deletions src/typechat.dialog/Message.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
// Copyright (c) Microsoft. All rights reserved.

using Microsoft.VisualBasic;

namespace Microsoft.TypeChat.Dialog;

public class Message<T> : IPromptSection
public class Message : IPromptSection
{
string _source;
T _body;
object _body;

public Message(T body)
public Message(object body)
: this(null, body)
{
}

public Message(string from, T body)
public Message(string from, object body)
{
if (string.IsNullOrEmpty(from))
{
Expand All @@ -23,10 +25,12 @@ public Message(string from, T body)
}

public string Source => _source;

public T Body => _body;

public object Body => _body;
public Type BodyType => _body.GetType();
public MessageHeaders? Headers { get; set; }
public object Attachment { get; set; }

public T GetBody<T>() => (T) _body;

public virtual string GetText()
{
Expand All @@ -36,6 +40,11 @@ public virtual string GetText()
}
return _body.Stringify();
}

public static implicit operator Message(string text) => new Message(text);
public static Message FromUser(object body) => new Message(body);
public static Message FromAssistant(object body) => new Message(PromptSection.Sources.Assistant, body);

}

public class MessageHeaders : Dictionary<string, string>
Expand All @@ -45,29 +54,3 @@ public MessageHeaders()
{
}
}

/// <summary>
/// General message
/// </summary>
public class Message : Message<object>
{
public Message(object body)
: base(body)
{
}

public Message(string source, object body)
: base(source, body)
{
}


public MessageHeaders? Headers { get; set; }

public object Attachment { get; set; }

public static implicit operator Message(string text) => new Message(text);

public static Message FromUser(object body) => new Message(body);
public static Message FromAssistant(object body) => new Message(PromptSection.Sources.Assistant, body);
}
19 changes: 17 additions & 2 deletions src/typechat.program/ProgramSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace Microsoft.TypeChat;

/// <summary>
/// A Json Program. See ProgramSchema.ts for the grammar for Programs
/// A Program is a set of steps, where each step is a function call.
/// Function calls can nest and take arguments that are Json values, arrays and objects
/// This class is the root is a simple AST for programs
/// </summary>
[JsonConverter(typeof(JsonProgramConvertor))]
Expand All @@ -20,6 +22,7 @@ public Steps? Steps

/// <summary>
/// Part or all of the user request that could not be translated into program steps
/// This is especially handy where the user asks has intent that cannot be mapped to existing APIs
/// </summary>
public string[] NotTranslated { get; set; }
}
Expand All @@ -36,6 +39,9 @@ public abstract partial class Expression
/// </summary>
public partial class Steps : Expression
{
/// <summary>
/// Currently, program steps are a collection of function calls
/// </summary>
public FunctionCall[] Calls
{
get;
Expand All @@ -45,6 +51,7 @@ public FunctionCall[] Calls

/// <summary>
/// A Function Call to a named function with zero or more arguments
/// This call is bound to the API targeted by this program.
/// </summary>
public partial class FunctionCall : Expression
{
Expand Down Expand Up @@ -79,6 +86,10 @@ public partial class ResultReference : Expression

/// <summary>
/// An expression representing a Json value
/// Supported Json types:
/// - string
/// - number
/// - boolean
/// </summary>
public partial class ValueExpr : Expression
{
Expand All @@ -90,10 +101,13 @@ public JsonElement Value
}

/// <summary>
/// An array expression - can contain any expression including function calls
/// An array expression - can contain any expression including Json objects and function calls
/// </summary>
public partial class ArrayExpr : Expression
{
/// <summary>
/// Any array can be a collection of any expression
/// </summary>
public Expression[] Value
{
get;
Expand All @@ -102,7 +116,8 @@ public Expression[] Value
}

/// <summary>
/// A Json Object.
/// A Json Object where the value can be any expression, including values returned
/// dynamically at runtime by function calls
/// </summary>
public partial class ObjectExpr : Expression
{
Expand Down
30 changes: 22 additions & 8 deletions src/typechat/JsonTranslatorPrompts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,40 @@ public class JsonTranslatorPrompts : IJsonTranslatorPrompts

public virtual Prompt CreateRequestPrompt(TypeSchema schema, Prompt request, IList<IPromptSection> preamble = null)
{
return RequestPrompt(schema.TypeFullName, schema.Schema, request, preamble);
return RequestPrompt(schema, request, preamble);
}

public virtual string CreateRepairPrompt(TypeSchema schema, string json, string validationError)
{
return RepairPrompt(validationError);
}

public static Prompt RequestPrompt(string typeName, string schema, Prompt request, IList<IPromptSection>? context = null)
public static Prompt RequestPrompt(TypeSchema typeSchema, Prompt request, IList<IPromptSection>? context = null)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
Prompt prompt = new Prompt();

prompt += IntroSection(typeName, schema);
prompt += IntroSection(typeSchema.TypeFullName, typeSchema.Schema);
AddContextAndRequest(prompt, request, context);

return prompt;
}

public static Prompt AddContextAndRequest(Prompt prompt, Prompt request, IList<IPromptSection> preamble)
/// <summary>
/// Add the given user request and any context to the prompt we are sending to the model
/// </summary>
/// <param name="prompt">prompt being constructed</param>
/// <param name="request">user request</param>
/// <param name="context">any RAG context</param>
/// <returns>prompt to send to the model</returns>
public static Prompt AddContextAndRequest(Prompt prompt, Prompt request, IList<IPromptSection> context)
{
if (!preamble.IsNullOrEmpty())
if (!context.IsNullOrEmpty())
{
prompt.Append(preamble);
prompt.Append(context);
}

if (request.Count == 1)
Expand All @@ -52,15 +59,22 @@ public static Prompt AddContextAndRequest(Prompt prompt, Prompt request, IList<I
return prompt;
}

static PromptSection IntroSection(string typeName, string schema)
/// <summary>
/// Adds a section that tells the model that its task to is translate requests into JSON matching the
/// given schema
/// </summary>
/// <param name="typeName"></param>
/// <param name="schema"></param>
/// <returns></returns>
public static PromptSection IntroSection(string typeName, string schema)
{
PromptSection introSection = new PromptSection();
introSection += $"You are a service that translates user requests into JSON objects of type \"{typeName}\" according to the following TypeScript definitions:\n";
introSection += $"###\n{schema}###\n";
return introSection;
}

public static PromptSection RequestSection(string request)
static PromptSection RequestSection(string request)
{
PromptSection requestSection = new PromptSection();
requestSection += "The following is a user request:\n";
Expand Down