V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
brader
V2EX  ›  程序员

Objective-C 对接 chatGPT 接口,怎么做到逐字输出

  •  
  •   brader · 352 天前 · 2734 次点击
    这是一个创建于 352 天前的主题,其中的信息可能已经有所发展或是发生改变。
    chatgpt 的
    https://api.openai.com/v1/chat/completions 接口,是支持流式响应的,stream=true ,我是服务端,接入的时候也是流式接收,并实时流式输出给了前端,我自己用浏览器测试了,确实是有一边接收一边输出的逐字输出效果的。

    然后我们 ios 前端,好像实现不了,他是一直等待接收完,一次输出所有文字的。

    我也不熟 Objective-C ,想请问下,Objective-C 能做到这个效果吗?可以给个大概的小 demo 吗
    18 条回复    2023-04-12 14:47:39 +08:00
    dayudayupao
        1
    dayudayupao  
       352 天前
    学习一下 sse ,gpt 官网就是用这个做的打字机效果的
    jethroX
        2
    jethroX  
       352 天前
    可以问:Objective-C 如何实现 SSE 流式接收数据?
    我试了下,能给出代码,但是我不知道实际运行起来是否可行。
    我在接入的时候,实际上都会让 GPT 帮我写一部分代码。
    ByteCat
        3
    ByteCat  
       352 天前
    了解一下 SSE ,如果你做服务端也可以转成 WebSocket 之类的来传,这样调用更方便一点,因为 SSE 规范只能用 GET 不能用 POST ,很多库没实现,要自己动手
    chuhades
        4
    chuhades  
       352 天前
    Objective-C 能够实现流式接收和逐字输出的效果。你可以使用 NSURLSession 来实现这一功能。以下是一个简单的示例,展示了如何使用 Objective-C 流式接收数据并逐字输出:

    ```
    #import <Foundation/Foundation.h>

    @interface StreamDemo : NSObject <NSURLSessionDataDelegate>
    @property (nonatomic, strong) NSMutableData *receivedData;
    @end

    @implementation StreamDemo

    - (instancetype)init {
    self = [super init];
    if (self) {
    _receivedData = [[NSMutableData alloc] init];
    }
    return self;
    }

    - (void)startStreamingRequest {
    NSString *urlString = @"https://api.openai.com/v1/chat/completions?stream=true";
    NSURL *url = [NSURL URLWithString:urlString];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"POST"];

    // 设置请求头信息
    [request setValue:@"your-api-key" forHTTPHeaderField:@"Authorization"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

    // 设置请求体信息
    NSDictionary *body = @{@"model": @"text-davinci-002",
    @"prompt": @"Your prompt here",
    @"max_tokens": @30};
    NSError *error;
    NSData *bodyData = [NSJSONSerialization dataWithJSONObject:body options:0 error:&error];
    if (error) {
    NSLog(@"Error creating request body: %@", error);
    return;
    }
    [request setHTTPBody:bodyData];

    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];

    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
    [dataTask resume];
    }

    #pragma mark - NSURLSessionDataDelegate

    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
    [self.receivedData appendData:data];

    // 在这里实现逐字输出的逻辑
    NSString *receivedString = [[NSString alloc] initWithData:self.receivedData encoding:NSUTF8StringEncoding];
    NSLog(@"Received Data: %@", receivedString);
    }

    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    if (error) {
    NSLog(@"Error: %@", error);
    } else {
    NSLog(@"Request completed successfully");
    }
    }

    @end

    int main(int argc, const char * argv[]) {
    @autoreleasepool {
    StreamDemo *streamDemo = [[StreamDemo alloc] init];
    [streamDemo startStreamingRequest];

    // 等待请求完成
    [[NSRunLoop currentRunLoop] run];
    }
    return 0;
    }
    ```

    请注意,这个示例仅用于演示目的,你需要根据你的需求对其进行调整。在实际应用中,你可能需要将这个代码与你的 iOS 项目结合起来,实现逐字输出到前端界面。
    churchill
        5
    churchill  
       352 天前
    说到底不就是一个长连接吗
    这些人被 AI 替代属实不冤
    mmnnyycc
        6
    mmnnyycc  
       352 天前
    @chuhades #4 这回答很标准的 chatgpt 的回答方式
    miromelo
        7
    miromelo  
       352 天前
    @mmnnyycc 这个就是 ChatGPT 回答的啊,他只是复制了一下而已
    brader
        8
    brader  
    OP
       352 天前
    @ByteCat 我当然了解 SSE 啊。。。不然我服务端怎么实现了接入 chatgpt 的 sse 格式的流响应,还把结果解析出来了,问题是前端不了解啊。。。他实现不出来,就说做不了
    brader
        10
    brader  
    OP
       352 天前
    @Alias4ck 你给的第一个链接的代码应该可以,我一个外行人看着都靠谱
    jethroX
        11
    jethroX  
       352 天前
    @ByteCat 这你就错了,我看了 ChatGPT 的请求,他就是用的 post 还有负载数据。我这边用的微软开源的一个 js sse 请求器。叫:@microsoft/fetch-event-source
    ByteCat
        12
    ByteCat  
       352 天前
    @jethroX 是啊,我指的就是 OpenAI stream 不是规范的 SSE ,不能用原生的 EventSource 获取数据,因为只支持 GET ,微软或者第三方实现的「可能」会支持比如 POST 的用法,但这个也可以自己实现,SSE 本身数据格式就比较简单。
    linhey
        13
    linhey  
       352 天前
    我这个库支持流式输出和 Tokenizer 估算
    https://github.com/AxApp/OpenAI
    brader
        14
    brader  
    OP
       351 天前
    @ByteCat
    @jethroX 我在服务端已经自实现了解析 SSE 消息,返回给前端的仅仅是纯文本结果,无须客户端做任何处理了。说到 gpt 的 sse ,就我所知,js 自带的 EventSource 是可用的,obj 语言不熟所以不清楚。而且我的情况而言,客户端并没有这方面的担忧,因为客户端对接面向的是经过我服务端中转的接口,我服务端这边是同时支持 GET 、POST 形式的
    jethroX
        15
    jethroX  
       351 天前
    @brader 那你的客户端没有和你的服务端流式传输?还是说用的 websocket 。如果是等着服务端获取完了消息再返回,那也太慢了吧。
    brader
        16
    brader  
    OP
       351 天前
    @jethroX
    @chuhades
    @churchill
    @Alias4ck
    @linhey 我在服务端已经成功把 SSE 数据解析出来了,然后直接把结果内容 content 纯文本输出给前端了,已经不需要客户端解析了,客户端收到什么数据就输出什么数据就行了,我自己直接把 url 贴到浏览器访问测试,已经是流输出的效果了,然后客户端自己搞不定,就说他接收到就是一次返回的,我很无语。。。领导拉我去小黑屋,也是说他比较菜,让他搞不知道要多久,搞不定的话,想让我转成 websocket 接口提供给他算了。。。

    下面我录制的浏览器测试视频,你们看看
    https://imgur.com/WSC80VO
    Ansen678
        17
    Ansen678  
       351 天前
    ios 跟服务器进行 websoket 连接,服务器去请求 chatgpt
    ByteCat
        18
    ByteCat  
       351 天前
    @brader 你这个算 SSE 吗?如果是的话,需要客户端以流方式接受才行,不然就是直接返回最后结果的,或者省得麻烦你就包成 WebSocket 来传,WS 比 SSE 调包容易一点😂可能你们的 iOSer 不懂这个
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2440 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 16:04 · PVG 00:04 · LAX 09:04 · JFK 12:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.