Comments (6)
Thank you. Yes, I agree with this idea.
One question: why append Async
suffix even though there is no synchronous alternative (i.e. SendAsync is the same the HttpClient has, but then GetCompletedResponseAsync is uhh, a long method name? :D
Anyways, I'll get back to working on this, will submit a PR soon.
from bingchat.
Maybe we can introduce another API?
For example:
public Task<BingChatResponse> SendAsync(string message);
class BingChatResponse : IAsyncEnumerable<string>
{
public IAsyncEnumerator<string> GetAsyncEnumerator();
public Task<string> GetCompletedResponseAsync();
}
Then the AskAsync
can simply be a wrapper for SendAsync
.
from bingchat.
Thanks for creating the discussion. I am also concerned about the problem of waiting too long for a complete answer.
I agree with the idea @neon-sunset provided, which allowing users to explicitly choose to receive a complete response or intermediate message. Here is my understanding. GetCompletedResponse
is an asynchronous method, which users should wait for a complete answer to be returned. ReadIntermediateMessages
is a synchronization method that users may call as many times as they wish to update the latest status.
I wonder if we can combine the two together. Based on the existing IBingChattable
interface, add an optional parameter as a callback function to the AskAsync
method. The definition is as follows
public interface IBingChattable
{
/// <summary>
/// Ask for a answer.
/// </summary>
/// <param name="message">Question content</param>
/// <param name="callback">Callback function for streaming response</param>
Task<string> AskAsync(string message, Action<string>? callback = null);
}
In this way, user provides a callback function, and the client passes the intermediate message (containing the previous part) to the user. Then user decides how to make updates, either by overwriting previous contents, or picking out the new parts and writing it.
Example codes for different users are as follows
//For single response
string answer = await conversation.AskAsync(prompt);
Console.WriteLine(answer);
//For streaming response - example 1
int lastCursorTop = Console.CursorTop;
string answer = await conversation.AskAsync(prompt, (string message) =>
{
//update
Console.SetCursorPosition(0, lastCursorTop);
Console.Write(message);
});
//final answer
Console.SetCursorPosition(0, lastCursorTop);
Console.WriteLine(answer);
//For streaming response - example 2
int lastCursorTop = Console.CursorTop;
int lastMessageLength = 0;
string answer = await conversation.AskAsync(prompt, (string message) =>
{
//update
Console.Write(message[lastMessageLength..]);
lastMessageLength = message.Length;
});
//final answer
Console.SetCursorPosition(0, lastCursorTop);
Console.WriteLine(answer);
What do you think of this?
from bingchat.
Ah, I think I did not explain it in full detail. The intention is to expose an object that represents a response state but it won't have any synchronization methods - it will be internally filled by websocket listener. The user will have the ability to either stream the intermediate messages with IAsyncEnumerable<string>
-returning method or simply wait for the complete response instead .GetCompletedResponse()
.
As for JS-style callbacks, I'm strictly opposed to their usage in C# unless absolutely necessary and would prefer to keep AskAsync
as simple as possible. The design does not assume whether it is used in CLI or as a component of mobile application, or anywhere else.
Ideally, it could be used as follows:
var response = client.Ask("Latest stock price of NVDA?");
await foreach (var msg in response)
{
// Append msg to however the response is displayed to the user
}
var completed = await response.GetFullResponse();
// Do whatever is appropriate to the context, like replacing previous output, doing nothing or something else entirely
with API probably (would like to know your point of view) looking like this:
class BingChatClientResponse : IAsyncEnumerable<string> // Shorter name?
{
public Task<string> GetFullResponse(CancellationToken ct = default);
public IAsyncEnumerator<string> GetAsyncEnumerator(CancellationToken ct = default);
}
This would also allow extending this class in the future when adding support for generating images, enumerating references used or providing other kinds of rich metadata.
from bingchat.
Thank you. Yes, I agree with this idea.
One question: why append
Async
suffix even though there is no synchronous alternative (i.e. SendAsync is the same the HttpClient has, but then GetCompletedResponseAsync is uhh, a long method name? :DAnyways, I'll get back to working on this, will submit a PR soon.
Then maybe GetFullResponseAsync
, GetCompletedAnswerAsync
or GetFullAnswerAsync
? :D
I think we should add the Async
suffix to fit the .NET naming convention. I think the reasons are as follows:
- Microsoft's documentation clearly states that publicly exposed asynchronous methods in .NET need to have the
Async
suffix. - Having the
Async
suffix clearly reflects that this is an asynchronous method without causing confusion, as this is the default naming convention for most official, or third-party libraries. - Even though we don't provide a synchronous method directly, users can write their own extension method to convert it to synchronous. This extension method can then be simply named without
Async
. As an example, Microsoft.Extensions.Hosting does this (IHost.StartAsync()
andHostExtensions.Start()
).
Anyways look good to me, thanks!
from bingchat.
(this is a tangent and a personal opinion)
Microsoft themselves do not follow the convention often. It is also outdated (pay attention the examples that start with events) and does not reflect modern state of the language. It was initially introduced in the early days of C# when a lot of code was synchronous and/or the distinction was necessary for methods that exposed both async and sync paths.
However, a lot of new code that deals with IO or just long-running operations often is async-only, and it is at this point strange to expect the developer to be unfamiliar with Task return type, especially given the popularity of the pattern in other languages such as JS/TS (Future/Promise), Rust (Future) and even Python (which too supposedly has await now?).
This is mostly a rant against five kilometers long method and type names in C# which will unfortunately continue plaguing it now that GPT-4 has also been trained on the swathes of poorly written C# code :(
It is probably best to just use your own judgement (like when to use a struct) than to strictly follow what the old docs say.
from bingchat.
Related Issues (20)
- Cookie no longer Required HOT 2
- Publish BingChat.Cli as tool to nuget HOT 1
- 404 Not found error while creating new conversation. HOT 6
- Question repeated in CLI reply HOT 2
- CLI reply missing source attributions HOT 2
- Cli reply text overlap HOT 3
- Can't read normally CookieFilePath From Cookie Editor HOT 4
- Timout until chat session expires? HOT 2
- Captcha Challenge HOT 2
- Number of requests left in a chat session? HOT 1
- request option to have results returned in json format HOT 1
- CaptchaChallenge: User needs to solve CAPTCHA to continue. HOT 8
- UnauthorizedRequest:I can ask 1 to 5 questions, but I can't ask any more after that. Why? HOT 1
- Project maintenance status
- CLI The server returned status code '200' when status code '101' was expected. HOT 3
- BingChat.BingChatException HResult=0x80131500 Message=UnauthorizedRequest: The conversationSignature is not set and is required to ensure that you have permission to use our APIs. IsAuthenticated=False. App ID= Source=BingChat HOT 1
- UnauthorizedRequest HOT 8
- CaptchaChallange without _U Cookie? HOT 2
- Run sample code throw The server returned status code '200' when status code '101' was expected
- Net Framework
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from bingchat.