Streaming ChatGPT OpenAI response

Hi guys, I created a custom action based on the streaming api tutorial FF put out for openai, but now code seem to have stopped working. I'm getting the streamed responses into my app, but the response handler function is only processing one response body or one token response before stopping. So there is no stream captured. Any ideas if this is a FF change or an error with my code? I've tested on emulator and web. So it seems like it's an error with my code.

tutorial
https://www.youtube.com/watch?v=ji2XbsDT_PY

code:
matic FlutterFlow imports

import '/backend/backend.dart';

import '/backend/schema/structs/index.dart';

import '/flutter_flow/flutter_flow_theme.dart';

import '/flutter_flow/flutter_flow_util.dart';

import 'index.dart'; // Imports other custom actions

import '/flutter_flow/custom_functions.dart'; // Imports custom functions

import 'package:flutter/material.dart';

// Begin custom action code

// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

// streamApiResponse.dart

import 'dart:convert';

import 'package:http/http.dart' as http;

var _client;

Future<void> streamApiResponse(

List<dynamic> jsonBody,

Future<dynamic> Function() callbackAction,

) async {

_client = http.Client();

final url = 'https://api.openai.com/v1/chat/completions';

final headers = {

'Content-Type': 'application/json',

'Authorization': 'Bearer ${FFAppState().apiKey}',

};

final String body = getApiBody(jsonBody);

final request = http.Request("POST", Uri.parse(url))

..headers.addAll(headers)

..body = body;

final http.StreamedResponse response = await _client.send(request);

FFAppState().addToChatHistory(ChatResponseStruct(

author: "assistant",

content: "",

));

response.stream.listen((List<int> value) {

final str = utf8.decode(value);

if (str.contains("data:")) {

final String data = str.split("data:")[1];

addToChatHistory(data, callbackAction);

}

});

}

void addToChatHistory(String data, Function callbackAction) {

if (data.contains("content")) {

final contentResponse = ContentResponse.fromJson(jsonDecode(data));

if (contentResponse.choices != null &&

contentResponse.choices![0].delta != null &&

contentResponse.choices![0].delta!.content != null) {

final content = contentResponse.choices![0].delta!.content!;

FFAppState().updateChatHistoryAtIndex(

FFAppState().chatHistory.length - 1,

(e) => e..content = "${e.content}$content",

);

callbackAction();

}

}

}

String getApiBody(dynamic jsonBody) {

final body = jsonEncode({

"model": "gpt-3.5-turbo",

"messages": jsonBody,

"stream": true,

});

return body;

}

class ContentResponse {

String? id;

String? object;

int? created;

String? model;

List<Choices>? choices;

ContentResponse({

this.id,

this.object,

this.created,

this.model,

this.choices,

});

factory ContentResponse.fromJson(Map<String, dynamic> json) {

return ContentResponse(

id: json['id'],

object: json['object'],

created: json['created'],

model: json['model'],

choices: json['choices'] != null

? List<Choices>.from(json['choices'].map((v) => Choices.fromJson(v)))

: null,

);

}

Map<String, dynamic> toJson() {

final Map<String, dynamic> data = <String, dynamic>{

'id': id,

'object': object,

'created': created,

'model': model,

'choices': choices?.map((v) => v.toJson()).toList(),

};

return data;

}

}

class Choices {

int? index;

Delta? delta;

String? finishReason;

Choices({this.index, this.delta, this.finishReason});

factory Choices.fromJson(Map<String, dynamic> json) {

return Choices(

index: json['index'],

delta: json['delta'] != null ? Delta.fromJson(json['delta']) : null,

finishReason: json['finish_reason'],

);

}

Map<String, dynamic> toJson() {

final Map<String, dynamic> data = <String, dynamic>{

'index': index,

'delta': delta?.toJson(),

'finish_reason': finishReason,

};

return data;

}

}

class Delta {

String? content;

Delta({this.content});

factory Delta.fromJson(Map<String, dynamic> json) {

return Delta(content: json['content']);

}

Map<String, dynamic> toJson() {

return {'content': content};

}

}

2
1 reply