-
-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* added more settings for llama sharp configuration * Agents * Fixed forgotten message limit exception * Changed MessagesLimitReachedException to InvalidOperationException
- Loading branch information
Showing
14 changed files
with
481 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
src/libs/LangChain.Core/Chains/StackableChains/Agents/AgentExecutorChain.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using LangChain.Abstractions.Chains.Base; | ||
using LangChain.Abstractions.Schema; | ||
using LangChain.Chains.HelperChains; | ||
using LangChain.Memory; | ||
using LangChain.Providers; | ||
using LangChain.Schema; | ||
|
||
namespace LangChain.Chains.StackableChains.Agents; | ||
|
||
public class AgentExecutorChain: BaseStackableChain | ||
{ | ||
public string HistoryKey { get; } | ||
private readonly BaseStackableChain _originalChain; | ||
|
||
private BaseStackableChain _chainWithHistory; | ||
|
||
public string Name { get; private set; } | ||
Check warning on line 17 in src/libs/LangChain.Core/Chains/StackableChains/Agents/AgentExecutorChain.cs GitHub Actions / Build, test and publish / Build, test and publish
|
||
|
||
/// <summary> | ||
/// Messages of this agent will not be added to the history | ||
/// </summary> | ||
public bool IsObserver { get; set; } = false; | ||
|
||
public AgentExecutorChain(BaseStackableChain originalChain, string name, string historyKey="history", | ||
Check warning on line 24 in src/libs/LangChain.Core/Chains/StackableChains/Agents/AgentExecutorChain.cs GitHub Actions / Build, test and publish / Build, test and publish
|
||
string outputKey = "final_answer") | ||
{ | ||
Name = name; | ||
HistoryKey = historyKey; | ||
_originalChain = originalChain; | ||
|
||
InputKeys = new[] { historyKey}; | ||
OutputKeys = new[] { outputKey }; | ||
|
||
SetHistory(""); | ||
} | ||
|
||
public void SetHistory(string history) | ||
{ | ||
|
||
_chainWithHistory = | ||
Chain.Set(history, HistoryKey) | ||
|_originalChain; | ||
} | ||
|
||
protected override async Task<IChainValues> InternalCall(IChainValues values) | ||
{ | ||
var res=await _chainWithHistory.CallAsync(values); | ||
return res; | ||
} | ||
} |
93 changes: 93 additions & 0 deletions
93
src/libs/LangChain.Core/Chains/StackableChains/Agents/GroupChat.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
using LangChain.Abstractions.Schema; | ||
using LangChain.Chains.HelperChains; | ||
using LangChain.Chains.HelperChains.Exceptions; | ||
using LangChain.Memory; | ||
using LangChain.Providers; | ||
|
||
namespace LangChain.Chains.StackableChains.Agents; | ||
|
||
public class GroupChat:BaseStackableChain | ||
{ | ||
private readonly IList<AgentExecutorChain> _agents; | ||
|
||
private readonly string _stopPhrase; | ||
private readonly int _messagesLimit; | ||
private readonly string _inputKey; | ||
private readonly string _outputKey; | ||
|
||
|
||
int _currentAgentId=0; | ||
private readonly ConversationBufferMemory _conversationBufferMemory; | ||
|
||
|
||
public bool ThrowOnLimit { get; set; } = false; | ||
public GroupChat(IList<AgentExecutorChain> agents, string? stopPhrase=null, int messagesLimit=10, string inputKey="input", string outputKey="output") | ||
Check warning on line 24 in src/libs/LangChain.Core/Chains/StackableChains/Agents/GroupChat.cs GitHub Actions / Build, test and publish / Build, test and publish
|
||
{ | ||
_agents = agents; | ||
|
||
_stopPhrase = stopPhrase; | ||
_messagesLimit = messagesLimit; | ||
_inputKey = inputKey; | ||
_outputKey = outputKey; | ||
_conversationBufferMemory = new ConversationBufferMemory(new ChatMessageHistory()) { AiPrefix = "", HumanPrefix = "", SystemPrefix = "", SaveHumanMessages = false }; | ||
InputKeys = new[] { inputKey }; | ||
OutputKeys = new[] { outputKey }; | ||
|
||
} | ||
|
||
public IReadOnlyList<Message> GetHistory() | ||
{ | ||
return _conversationBufferMemory.ChatHistory.Messages; | ||
} | ||
|
||
|
||
protected override async Task<IChainValues> InternalCall(IChainValues values) | ||
{ | ||
|
||
await _conversationBufferMemory.Clear().ConfigureAwait(false); | ||
foreach (var agent in _agents) | ||
{ | ||
agent.SetHistory(""); | ||
} | ||
var firstAgent = _agents[0]; | ||
var firstAgentMessage = (string)values.Value[_inputKey]; | ||
await _conversationBufferMemory.ChatHistory.AddMessage(new Message($"{firstAgent.Name}: {firstAgentMessage}", | ||
MessageRole.System)).ConfigureAwait(false); | ||
int messagesCount = 1; | ||
while (messagesCount<_messagesLimit) | ||
{ | ||
var agent = GetNextAgent(); | ||
agent.SetHistory(_conversationBufferMemory.BufferAsString+"\n"+$"{agent.Name}:"); | ||
var res = await agent.CallAsync(values).ConfigureAwait(false); | ||
var message = (string)res.Value[agent.OutputKeys[0]]; | ||
if (message.Contains(_stopPhrase)) | ||
{ | ||
break; | ||
} | ||
|
||
if (!agent.IsObserver) | ||
{ | ||
await _conversationBufferMemory.ChatHistory.AddMessage(new Message($"{agent.Name}: {message}", | ||
MessageRole.System)).ConfigureAwait(false); | ||
} | ||
} | ||
|
||
var result = _conversationBufferMemory.ChatHistory.Messages.Last(); | ||
messagesCount = _conversationBufferMemory.ChatHistory.Messages.Count; | ||
if (ThrowOnLimit && messagesCount >= _messagesLimit) | ||
{ | ||
throw new InvalidOperationException($"Message limit reached:{_messagesLimit}"); | ||
} | ||
values.Value.Add(_outputKey, result); | ||
return values; | ||
|
||
} | ||
|
||
AgentExecutorChain GetNextAgent() | ||
{ | ||
_currentAgentId++; | ||
if (_currentAgentId >= _agents.Count) | ||
_currentAgentId = 0; | ||
return _agents[_currentAgentId]; | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
src/libs/LangChain.Core/Chains/StackableChains/Agents/PromptedAgent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using LangChain.Chains.HelperChains; | ||
using LangChain.Providers; | ||
|
||
namespace LangChain.Chains.StackableChains.Agents; | ||
|
||
public class PromptedAgent: AgentExecutorChain | ||
{ | ||
public const string Template = | ||
@"{system} | ||
{history}"; | ||
|
||
private static BaseStackableChain MakeChain(string name, string system, IChatModel model, string outputKey) | ||
{ | ||
return Chain.Set(system, "system") | ||
| Chain.Template(Template) | ||
| Chain.LLM(model,outputKey: outputKey); | ||
} | ||
|
||
|
||
public PromptedAgent(string name, string prompt, IChatModel model, string outputKey = "final_answer") : base(MakeChain(name,prompt,model, outputKey),name, "history", outputKey) | ||
{ | ||
|
||
} | ||
} |
134 changes: 134 additions & 0 deletions
134
src/libs/LangChain.Core/Chains/StackableChains/Agents/ReActAgentExecutorChain.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
using LangChain.Abstractions.Chains.Base; | ||
using LangChain.Abstractions.Schema; | ||
using LangChain.Chains.HelperChains; | ||
using LangChain.Chains.StackableChains.ReAct; | ||
using LangChain.Memory; | ||
using LangChain.Providers; | ||
using LangChain.Schema; | ||
using System.Reflection; | ||
using static LangChain.Chains.Chain; | ||
|
||
namespace LangChain.Chains.StackableChains.Agents; | ||
|
||
public class ReActAgentExecutorChain : BaseStackableChain | ||
{ | ||
public const string DefaultPrompt = | ||
@"Answer the following questions as best you can. You have access to the following tools: | ||
{tools} | ||
Use the following format: | ||
Question: the input question you must answer | ||
Thought: you should always think about what to do | ||
Action: the action to take, should be one of [{tool_names}] | ||
Action Input: the input to the action | ||
Observation: the result of the action | ||
(this Thought/Action/Action Input/Observation can repeat multiple times) | ||
Thought: I now know the final answer | ||
Final Answer: the final answer to the original input question | ||
Always add [END] after final answer | ||
Begin! | ||
Question: {input} | ||
Thought:{history}"; | ||
|
||
private IChain? _chain = null; | ||
private bool _useCache; | ||
Dictionary<string, ReActAgentTool> _tools = new(); | ||
private readonly IChatModel _model; | ||
private readonly string _reActPrompt; | ||
private readonly int _maxActions; | ||
private readonly ConversationBufferMemory _conversationBufferMemory; | ||
|
||
|
||
public ReActAgentExecutorChain(IChatModel model, string reActPrompt = null, int maxActions = 5, string inputKey = "answer", | ||
string outputKey = "final_answer") | ||
{ | ||
reActPrompt ??= DefaultPrompt; | ||
_model = model; | ||
_reActPrompt = reActPrompt; | ||
_maxActions = maxActions; | ||
|
||
InputKeys = new[] { inputKey }; | ||
OutputKeys = new[] { outputKey }; | ||
|
||
_conversationBufferMemory = new ConversationBufferMemory(new ChatMessageHistory()) { AiPrefix = "", HumanPrefix = "", SystemPrefix = "", SaveHumanMessages = false }; | ||
|
||
} | ||
|
||
private string? _userInput = null; | ||
private const string ReActAnswer = "answer"; | ||
private void InitializeChain() | ||
{ | ||
string tool_names = string.Join(",", _tools.Select(x => x.Key)); | ||
string tools = string.Join("\n", _tools.Select(x => $"{x.Value.Name}, {x.Value.Description}")); | ||
|
||
var chain = | ||
Set(() => _userInput, "input") | ||
| Set(tools, "tools") | ||
| Set(tool_names, "tool_names") | ||
| Set(() => _conversationBufferMemory.BufferAsString, "history") | ||
| Template(_reActPrompt) | ||
| Chain.LLM(_model).UseCache(_useCache) | ||
| UpdateMemory(_conversationBufferMemory, requestKey: "input", responseKey: "text") | ||
| ReActParser(inputKey: "text", outputKey: ReActAnswer); | ||
|
||
_chain = chain; | ||
} | ||
|
||
protected override async Task<IChainValues> InternalCall(IChainValues values) | ||
{ | ||
|
||
var input = (string)values.Value[InputKeys[0]]; | ||
var values_chain = new ChainValues(); | ||
|
||
_userInput = input; | ||
|
||
|
||
if (_chain == null) | ||
{ | ||
InitializeChain(); | ||
} | ||
|
||
for (int i = 0; i < _maxActions; i++) | ||
{ | ||
var res = await _chain.CallAsync(values_chain); | ||
if (res.Value[ReActAnswer] is AgentAction) | ||
{ | ||
var action = (AgentAction)res.Value[ReActAnswer]; | ||
var tool = _tools[action.Action]; | ||
var tool_res = tool.ToolCall(action.ActionInput); | ||
await _conversationBufferMemory.ChatHistory.AddMessage(new Message("Observation: " + tool_res, MessageRole.System)) | ||
.ConfigureAwait(false); | ||
await _conversationBufferMemory.ChatHistory.AddMessage(new Message("Thought:", MessageRole.System)) | ||
.ConfigureAwait(false); | ||
continue; | ||
} | ||
else if (res.Value[ReActAnswer] is AgentFinish) | ||
{ | ||
var finish = (AgentFinish)res.Value[ReActAnswer]; | ||
values.Value.Add(OutputKeys[0], finish.Output); | ||
return values; | ||
} | ||
} | ||
|
||
|
||
|
||
return values; | ||
} | ||
|
||
public ReActAgentExecutorChain UseCache(bool enabled = true) | ||
{ | ||
_useCache = enabled; | ||
return this; | ||
} | ||
|
||
|
||
public ReActAgentExecutorChain UseTool(ReActAgentTool tool) | ||
{ | ||
_tools.Add(tool.Name, tool); | ||
return this; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
src/libs/LangChain.Core/Chains/StackableChains/ReAct/ReActAgentTool.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
namespace LangChain.Chains.StackableChains.ReAct; | ||
|
||
public class ReActAgentTool | ||
{ | ||
public ReActAgentTool(string name, string description, Func<string, string> func) | ||
{ | ||
Name = name; | ||
Description = description; | ||
ToolCall = func; | ||
} | ||
|
||
public string Name { get; set; } | ||
public string Description { get; set; } | ||
|
||
public Func<string, string> ToolCall { get; set; } | ||
|
||
} |
Oops, something went wrong.