Skip to content

Commit

Permalink
Merge pull request open-runtimes#91 from ffex/feat-4498-deepgram-audi…
Browse files Browse the repository at this point in the history
…o-summary

added a deepgramAudioSummary() Function using Java
  • Loading branch information
christyjacob4 committed Feb 19, 2023
2 parents 186b160 + 7151a5c commit 87d306c
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 0 deletions.
182 changes: 182 additions & 0 deletions java/deepgram_audio_summary/Index.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import java.util.Collections;
import java.util.stream.Collectors;
import java.util.*;
import java.util.stream.*;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;

import com.google.gson.Gson;
import org.apache.commons.validator.routines.UrlValidator;

final Gson gson=new Gson();

public RuntimeResponse main(RuntimeRequest req,RuntimeResponse res)throws Exception{
// Validate that values present in the request are not empty (payload, variables)
RuntimeResponse errorResponse=checkEmptyPayloadAndVariables(req,res);
if(errorResponse!=null){
return errorResponse;
}

// Validate the requested payload (URL)
String payloadString=req.getPayload().toString();

errorResponse=validatePayload(payloadString,res);
if(errorResponse!=null){
return errorResponse;
}

Map<String, Object> payload = gson.fromJson(payloadString,Map.class);

// Get file url from payload
String fileurl=payload.get("fileUrl").toString();

// Name API key is not empty
String apiKeyVariable="DEEPGRAM_SECRET_KEY";

errorResponse=checkEmptyAPIKey(req,res,apiKeyVariable);
if(errorResponse!=null){
return errorResponse;
}

String apiKey=req.getVariables().get(apiKeyVariable).toString();

String deepgramData="";
Map<String, Object> responseData=new HashMap<>();

try{
deepgramData=generateSummary(fileurl,apiKey);
}catch(Exception e){
responseData.put("success",false);
responseData.put("message","Something went wrong while generating the summary, please check with the developers. Error: "+e.getMessage());//TODO
return res.json(responseData);
}
responseData.put("success",true);
responseData.put("deepgramData",deepgramData);

return res.json(responseData);
}


/**
* This method will send a POST request to the specified endpoint and return the Deepgram's response
*
* @param requestBody is the Request Body for the POST request containing the URL to the wav file to Summarize
* @param apiKey is the access token used by Deepgram to summarize
* @return the Deepgram's response to the POST request
* @throws Exception in case of malformed URL, I/O exception, etc.
*/
private String generateSummary(String requestBody,String apiKey)throws Exception{
String endpointUrl="https://api.deepgram.com/v1/listen?summarize=true&punctuate=true";
URL url=new URL(endpointUrl);
HttpURLConnection con=(HttpURLConnection)url.openConnection();

con.setRequestMethod("POST");
con.setRequestProperty("Content-Type","application/json");
con.setRequestProperty("Authorization","Token "+apiKey);

con.setDoOutput(true);

//prepare request body
requestBody="{\"url\":\""+requestBody+"\"}";

OutputStream os=con.getOutputStream();
byte[] input=requestBody.getBytes("utf-8");
os.write(input,0,input.length);

StringBuilder response=new StringBuilder();

BufferedReader br=new BufferedReader(new InputStreamReader(con.getInputStream(),"utf-8"));
String responseLine=null;
while((responseLine=br.readLine())!=null){
response.append(responseLine.trim());
}

br.close();
con.disconnect();

return response.toString();
}

/**
* This method validates that a non-empty API key is present in variables
*
* @param req is the received POST request
* @return null if non-empty API key is present, otherwise an error response
*/
private RuntimeResponse checkEmptyAPIKey(RuntimeRequest req,RuntimeResponse res,String apiKeyVariable){
Map<String, String> variables=req.getVariables();

if(!variables.containsKey(apiKeyVariable) ||variables.get(apiKeyVariable)==null||variables.get(apiKeyVariable).trim().isEmpty()){
Map<String, Object> responseData=new HashMap<>();
responseData.put("success",false);
responseData.put("message","Please pass a non-empty API Key "+apiKeyVariable+" for Deepgram");

return res.json(responseData);
}

return null;
}
/**
* This method validates that non-empty URL is present in the payload
*
* @param payload is the object that contains the URL
* @return null if payload is valid, otherwise an error response
*/
private RuntimeResponse validatePayload(String payloadString,RuntimeResponse res){
Map<String, Object> responseData=new HashMap<>();
Map<String, Object> payload=new HashMap<>();;
try{
payload=gson.fromJson(payloadString,Map.class);
} catch (Exception e) {
responseData.put("success",false);
responseData.put("message","The payload is invalid. Example of valid payload:{\"fileUrl\": \"...\"}");
return res.json(responseData);
}

// Validate that payload has fileUrl
if(!payload.containsKey("fileUrl")){
responseData.put("success",false);
responseData.put("message","Please provide a valid file URL");
return res.json(responseData);
}

String fileUrl=payload.get("fileUrl").toString();

// Validate the URL
UrlValidator urlValidator=new UrlValidator();
if(!urlValidator.isValid(fileUrl)){
responseData.put("success",false);
responseData.put("message","Provided URL: "+fileUrl+" is not valid, please provide a valid, correctly formed URL");
return res.json(responseData);
}

return null;
}
/**
* This function will validate that the payload and variables are non-empty in the request
*
* @param req is the received POST request
* @return null is nothing is empty, otherwise an error response
*/
private RuntimeResponse checkEmptyPayloadAndVariables(RuntimeRequest req,RuntimeResponse res){

Map<String, Object> responseData=new HashMap<>();

if(req.getPayload()==null||req.getPayload().trim().isEmpty()||req.getPayload().trim().equals("{}")){
responseData.put("success",false);
responseData.put("message","Payload is empty, expected a payload with provider and URL");
return res.json(responseData);

}
if(req.getVariables()==null){
responseData.put("success",false);
responseData.put("message","Empty function variables found. You need to pass an API key for the provider");
return res.json(responseData);
}

return null;
}
59 changes: 59 additions & 0 deletions java/deepgram_audio_summary/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# 💻 Deepgram Audio Summary

A Java Cloud Function for generating a summary using [Deepgram](https://deepgram.com/)

_Deepgram Example input:_

```json
{"fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav"}
```
_Deepgram Example output:_

```json
{
"success": true,
"deepgramData": {}
}
```

_Error Example output:_

```json
{
"success": false,
"message":"Please provide a valid file URL."
}
```


## 📝 Variables

List of variables used by this cloud function. These must be passed within 'variables' section of the request:

**DEEPGRAM_SECRET_KEY** - This API key would be the access token used by Deepgram for generating the Summary.

## 🚀 Deployment

1. Clone this repository, and enter this function folder:

```
$ git clone https://github.com/open-runtimes/examples.git && cd examples
$ cd java/deepgram_audio_summary
```

2. Enter this function folder and build the code:
```
docker run -e INTERNAL_RUNTIME_ENTRYPOINT=Index.java --rm --interactive --tty --volume $PWD:/usr/code openruntimes/java:v2-11.0 sh /usr/local/src/build.sh
```
As a result, a `code.tar.gz` file will be generated.

3. Start the Open Runtime:
```
docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/java:v2-11.0 sh /usr/local/src/start.sh
```

Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Java runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/java-11.0).

## 📝 Notes
- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions).
- This example is compatible with Java 11.0. Other versions may work but are not guarenteed to work as they haven't been tested.
4 changes: 4 additions & 0 deletions java/deepgram_audio_summary/deps.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dependencies {
implementation 'com.google.code.gson:gson:2.9.0'
implementation 'commons-validator:commons-validator:1.7'
}

0 comments on commit 87d306c

Please sign in to comment.