Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <title>Responsible Prompting Demo</title> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <link rel="stylesheet" href="https://unpkg.com/carbon-components/css/carbon-components.min.css"> | |
| <script type="text/javascript" src="static/demo/js/d3.v7.min.js"></script> | |
| <script type="text/javascript" src="static/demo/js/jquery-3.7.1.min.js"></script> | |
| <style type="text/css"> | |
| div.tooltip { | |
| position: absolute; | |
| text-align: left; | |
| padding: 0.5em; | |
| width: 20em; | |
| min-height: 5em; | |
| background: #fff; | |
| color: #000; | |
| border: 1px solid #000; | |
| border-radius: 5px; | |
| pointer-events: none; | |
| font-size: inherit; | |
| font-family: inherit; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="bx--grid"> | |
| <div class="bx--row"> | |
| <div class="bx--col-lg-10 bx--offset-lg-1"> | |
| <h1 class="bx--type-expressive-heading-03" style="margin-top: 1em;">Responsible Prompting</h1> | |
| <p class="bx--type-body-long-01"><br>Please provide a prompt that would be sent to an LLM. Recommendations are performed in prompting-time, before content generation. The recommendations consider a curated dataset of values and prompts sentences. The recommendations are based on the similarity between the input sentences and our prompt sentences dataset.<br><br></p> | |
| <div class="bx--tabs"> | |
| <ul class="bx--tabs__nav"> | |
| <li class="bx--tabs__nav-item bx--tabs__nav-item--selected" id="tab-1" data-target="#tab-content-1"> | |
| <a class="bx--tabs__nav-link" href="#" onclick="$('#tab-content-1').toggle();$('#tab-1').toggleClass('bx--tabs__nav-item--selected');$('#tab-content-2').toggle();$('#tab-2').toggleClass('bx--tabs__nav-item--selected');">Prompt</a> | |
| </li> | |
| <li class="bx--tabs__nav-item" data-target="#tab-content-2" id="tab-2"> | |
| <a class="bx--tabs__nav-link" href="#" onclick="$('#tab-content-1').toggle();$('#tab-1').toggleClass('bx--tabs__nav-item--selected');$('#tab-content-2').toggle();$('#tab-2').toggleClass('bx--tabs__nav-item--selected');renderGraph($('#prompt').data('recommendations'))">Graph</a> | |
| </li> | |
| </ul> | |
| </div> | |
| <form class="bx--form" id="demo"> | |
| <div class="bx--tab-content"> | |
| <div id="tab-content-1" class="bx--tab-content__section"> | |
| <div class="bx--form-item"> | |
| <textarea id="prompt" name="prompt" class="bx--text-area" rows="15" placeholder="Enter your prompt">Act as a professional designer with 20 years of experience creating and testing UX interfaces and landing sites for a variety of IT applications. We are in need of more people and an increased budget to be able to keep up with clients' needs. What kind of evidence should I gather to support my demands to gain more resources?</textarea> | |
| <div id="recommendation" style="min-height: 3em;" class="bx--form__helper-text"></div> | |
| </div> | |
| </div> | |
| <div id="tab-content-2" class="bx--tab-content__section bx--tab-content--hidden" style="display: none;"> | |
| <div class="bx--form-item" id="graph" style="background: #efefef"></div> | |
| </div> | |
| </div> | |
| <div class="bx--form-item" style="margin-bottom: 2em;"> | |
| <button id="generate" type="submit" class="bx--btn bx--btn--primary">Generate</button> | |
| </div> | |
| <div class="bx--form-item"> | |
| <label for="outcome" id="outcome-label" class="bx--label">Generated text</label> | |
| <textarea id="outcome" name="outcome" class="bx--text-area" rows="12" placeholder=""></textarea> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| <script src="./js/jquery-3.7.1.min.js"></script> | |
| <script lang="javascript"> | |
| const width = 600; | |
| const height = 200; | |
| const marginTop = 30; | |
| const marginRight = 30; | |
| const marginBottom = 30; | |
| const marginLeft = 30; | |
| const nodeRadius = 3; | |
| const svg = d3.select("#graph").append("svg") | |
| .attr("viewBox", [0, 0, width, height]) | |
| .attr("style", "max-width: 100%; height: auto; font: 8px sans-serif;"); | |
| var tooltip = d3.select("body").append("div") | |
| .attr("class", "tooltip") | |
| .style("opacity", 0); | |
| const renderGraph = (recommendations) => { | |
| if( !recommendations ){ | |
| return ; | |
| } | |
| svg.selectAll("*").remove(); // Clearing previous plots | |
| var graphData = {nodes: [], edges: []} | |
| var i = j = 0; | |
| if( recommendations['input'].length > 0 ){ | |
| graphData.nodes.push({ | |
| id: 0, | |
| x: Number(recommendations['input'][0].x), | |
| y: Number(recommendations['input'][0].y), | |
| text: recommendations['input'][0].sentence, | |
| label: 'S' + (i+1), | |
| type: 'input' | |
| }) | |
| for( i = 1; i < recommendations['input'].length; i++ ){ | |
| graphData.nodes.push({ | |
| id: i, | |
| x: Number(recommendations['input'][i].x), | |
| y: Number(recommendations['input'][i].y), | |
| text: recommendations['input'][i].sentence, | |
| label: 'S' + (i+1), | |
| type: 'input' | |
| }); | |
| graphData.edges.push({ source: (i-1), target: i, type: 'input' }); | |
| } | |
| } | |
| // Adding nodes & edges for inclusion recommendations | |
| if( recommendations['add'].length > 0 ){ | |
| for( j = 0; j < recommendations['add'].length; j++ ){ | |
| graphData.nodes.push({ | |
| id: i + j + 1, | |
| x: Number(recommendations['add'][j].x), | |
| y: Number(recommendations['add'][j].y), | |
| text: recommendations['add'][j].prompt, | |
| label: recommendations['add'][j].value, | |
| type: 'add' | |
| }); | |
| graphData.edges.push({ source: (i-1), target: (i+j+1), type: 'add' }); | |
| } | |
| } | |
| // Adding nodes & edges for removal recommendations | |
| if( recommendations['remove'].length > 0 ){ | |
| // Showing only the first removal recommendation | |
| graphData.nodes.push({ | |
| id: i + j, | |
| x: Number(recommendations['remove'][0].x), | |
| y: Number(recommendations['remove'][0].y), | |
| text: recommendations['remove'][0].closest_harmful_sentence, | |
| label: recommendations['remove'][0].value, | |
| type: 'remove' | |
| }); | |
| } | |
| // Convert edge references to actual node objects | |
| graphData.edges = graphData.edges.map(edge => ({ | |
| source: graphData.nodes.find(n => n.id === edge.source), | |
| target: graphData.nodes.find(n => n.id === edge.target) | |
| })); | |
| const { nodes, edges } = graphData; | |
| // Prepare the ranges of values for the axes | |
| const xDomain = d3.extent(nodes, d => d.x); | |
| const yDomain = d3.extent(nodes, d => d.y); | |
| const xPadding = 2 | |
| const yPadding = 2 | |
| // Prepare the scales for positional encoding. | |
| const x = d3.scaleLinear() | |
| .domain([xDomain[0]-xPadding,xDomain[1]+xPadding]).nice() | |
| .range([marginLeft, width - marginRight]); | |
| const y = d3.scaleLinear() | |
| .domain([yDomain[0]-yPadding,yDomain[1]+yPadding]).nice() | |
| .range([height - marginBottom, marginTop]); | |
| // Create the axes. | |
| svg.append("g") | |
| .attr("transform", `translate(0,${height - marginBottom})`) | |
| .call(d3.axisBottom(x).ticks(width / 80)) | |
| .call(g => g.select(".domain").remove()) | |
| .call(g => g.append("text") | |
| .attr("x", width) | |
| .attr("y", marginBottom - 4) | |
| .attr("fill", "currentColor") | |
| .attr("text-anchor", "end") | |
| .text("Semantic dimension 1")); | |
| svg.append("g") | |
| .attr("transform", `translate(${marginLeft},0)`) | |
| .call(d3.axisLeft(y)) | |
| .call(g => g.select(".domain").remove()) | |
| .call(g => g.append("text") | |
| .attr("x", -marginLeft) | |
| .attr("y", 10) | |
| .attr("fill", "currentColor") | |
| .attr("text-anchor", "start") | |
| .text("Semantic dimension 2")); | |
| // Create the grid. | |
| svg.append("g") | |
| .attr("stroke", "#cccccc") | |
| .attr("stroke-opacity", 0.5) | |
| .call(g => g.append("g") | |
| .selectAll("line") | |
| .data(x.ticks()) | |
| .join("line") | |
| .attr("x1", d => 0.5 + x(d)) | |
| .attr("x2", d => 0.5 + x(d)) | |
| .attr("y1", marginTop) | |
| .attr("y2", height - marginBottom)) | |
| .call(g => g.append("g") | |
| .selectAll("line") | |
| .data(y.ticks()) | |
| .join("line") | |
| .attr("y1", d => 0.5 + y(d)) | |
| .attr("y2", d => 0.5 + y(d)) | |
| .attr("x1", marginLeft) | |
| .attr("x2", width - marginRight)); | |
| // Add a layer of dots. | |
| svg.append("g") | |
| .attr("stroke-width", 2.5) | |
| .attr("stroke-opacity", 0.5) | |
| .attr("fill", "none") | |
| .selectAll("circle") | |
| .data(nodes) | |
| .join("circle") | |
| .attr("stroke", d => d.type == "add" ? "green" : d.type == "input"? "#666" : "red" ) | |
| .attr("cx", d => x(d.x)) | |
| .attr("cy", d => y(d.y)) | |
| .attr("r", nodeRadius); | |
| // Add a layer of labels. | |
| svg.append("g") | |
| .attr("font-family", "sans-serif") | |
| .attr("text-opacity", 0.5) | |
| .attr("font-size", 8) | |
| .selectAll("text") | |
| .data(nodes) | |
| .join("text") | |
| .attr("dy", "0.35em") | |
| .attr("x", d => x(d.x)+5) | |
| .attr("y", d => y(d.y)) | |
| .text(d => d.label) | |
| .on('mousemove', function (d, i) { | |
| d3.select(this).transition() | |
| .duration("50") | |
| .attr("text-opacity", 1.0) | |
| .attr("stroke", "white") | |
| .attr("stroke-width", 3) | |
| .style("paint-order", "stroke fill") | |
| .attr("fill", d => d.type == "add" ? "green" : d.type == "input"? "black" : "red" ) | |
| tooltip.transition() | |
| .duration(50) | |
| .style("opacity", 1); | |
| tooltip.html( "<strong>" + i.label + ":</strong><br>" + i.text ) | |
| .style("left", (event.pageX + 10) + "px") | |
| .style("top", (event.pageY + 10) + "px"); | |
| ; | |
| }) | |
| .on('mouseout', function (d, i) { | |
| d3.select(this).transition() | |
| .duration("50") | |
| .attr("text-opacity", 0.5) | |
| .attr("stroke-width", 0) | |
| .style("paint-order", "stroke fill") | |
| .attr("fill", "black") | |
| tooltip.transition() | |
| .duration(50) | |
| .style("opacity", 0); | |
| }); | |
| // Adding edges | |
| svg.append("g") | |
| .selectAll("line") | |
| .data(edges) | |
| .join("line") | |
| .attr("stroke", "#666") | |
| .attr("stroke-opacity", 0.5) | |
| .attr("x1", d => x(d.source.x)+(d.source.x<d.target.x?1.3*nodeRadius:nodeRadius*-1.3)) | |
| .attr("y1", d => y(d.source.y)) | |
| .attr("x2", d => x(d.target.x)+(d.source.x>d.target.x?1.3*nodeRadius:nodeRadius*-1.3)) | |
| .attr("y2", d => y(d.target.y)) | |
| .style("stroke-dasharray", d => d.target.type == "add" ? "3,3" : ""); | |
| }; | |
| // ------------------------------------------------ | |
| // Init state | |
| if( $( "#prompt" ).val() == "" ){ | |
| $( "#generate" ).attr( "disabled", true ) ; | |
| } | |
| var last_request = Date.now() - 60 * 60 * 1000 ; | |
| var last_prompt = $( "#prompt" ).val().trim() ; | |
| // Add recommendations to the prompt | |
| function add_recommendation( p ){ | |
| preview_add_recommendation( p, "hide" ) | |
| $( "#prompt" ).val( $( "#prompt" ).val() + " " + p ) ; | |
| $( "#recommendation" ).html( "" ) ; | |
| $( "#prompt" ).trigger( "keyup" ) ; // Looking for recommendations after accepting a recommendation | |
| } | |
| // Preview for add recommendation | |
| function preview_add_recommendation( p, flag ){ | |
| if( flag == "show" ){ | |
| $( "#prompt" ).val( $( "#prompt" ).val() + " " + p ) ; | |
| } | |
| else{ | |
| $( "#prompt" ).val( $( "#prompt" ).val().replace( " " + p, "" ) ) ; | |
| } | |
| } | |
| // Remove adversarial sentences from prompt | |
| function remove_recommendation( p ){ | |
| $( "#prompt" ).val( $( "#prompt" ).val().replace( p, "" ) ) ; | |
| $( "#prompt" ).val( $( "#prompt" ).val().replace( " ", " " ) ) ; | |
| $( "#recommendation" ).html( "" ) ; | |
| $( "#prompt" ).trigger( "keyup" ) ; // Looking for recommendations after accepting a recommendation | |
| } | |
| // Preview for add recommendation | |
| function preview_remove_recommendation( p, flag ){ | |
| if( flag == "show" ){ | |
| $( "#prompt" ).data( "previous_prompt", $( "#prompt" ).val() ) ; | |
| $( "#prompt" ).val( $( "#prompt" ).val().replace( p, "" ) ) ; | |
| } | |
| else{ | |
| $( "#prompt" ).val( $( "#prompt" ).data( "previous_prompt" ) ) ; | |
| } | |
| } | |
| // Listening to changes performed on the prompt input field | |
| $( "#prompt" ).on( "keyup", function( e ){ | |
| // Updating the generate button state based on prompt length | |
| if( $( "#prompt" ).val().length > 0 ){ | |
| $( "#generate" ).removeAttr( "disabled" ) ; | |
| } | |
| else{ | |
| $( "#generate" ).attr( "disabled", true ) ; | |
| } | |
| // Minimum timeout between the requests | |
| if( Date.now() - last_request > 500 && last_prompt != $( "#prompt" ).val().trim() ){ | |
| last_request = Date.now() ; | |
| last_prompt = $( "#prompt" ).val().trim() ; | |
| // Getting the last typed char | |
| var last_char = $( "#prompt" ).val().trim().slice( -1 ) ; | |
| // Triggering the API request when ending of a sentence is found, e.g., .?! | |
| if( last_char == "." || last_char == "?" || last_char == "!" ){ | |
| $( "#recommendation" ).html( 'Requesting recommendations: <div class="bx--tag bx--tag--gray bx--tag--deletable">...</div>' ) ; | |
| var api_url = "/recommend?prompt=" | |
| // var api_url = "/recommend_local?prompt=" | |
| var p = $( "#prompt" ).val() ; | |
| // API request | |
| $.getJSON( api_url + encodeURI( p ), function( data ) { | |
| $( "#recommendation" ).html( "Recommendations: " ) ; | |
| // Looking first for removal recommendations | |
| // if( data["remove"].length > 0 && data["remove"][0].similarity > 0.5 ){ | |
| if( data["remove"].length > 0 ){ | |
| for( var i = 0; i < data["remove"].length ; i++ ){ | |
| // $( "#prompt" ).html( $( "#prompt" ).html().replace( data["remove"][i].sentence, '<span style="text-decoration: underline red">' + data["remove"][i].sentence + '</span>' ) ) ; | |
| var sentence = data["remove"][i].sentence.replaceAll( "'", "\\'" ) ; | |
| var sentence_entity = data["remove"][i].sentence.replaceAll( "'", "'" ) ; | |
| var sentence_value = data["remove"][i].value.replaceAll( "'", "\\'" ) ; | |
| $( "#recommendation" ).append( '<div class="bx--tag bx--tag--red bx--tag--deletable" style="cursor: pointer;" onmouseover="preview_remove_recommendation(\''+ sentence + '\', \'show\')" onmouseout="preview_remove_recommendation(\''+ sentence + '\', \'hide\')" onclick="remove_recommendation(\''+ sentence + '\')">x ' + sentence_value + '</div>' ) ; | |
| break ; // Showing only once removal recommendation at a time | |
| } | |
| } | |
| // else if( data["add"].length > 0 ){ // After the removal recommendations are dealt with, then we show recommendations for inclusion | |
| if( data["add"].length > 0 ){ // Think Demo UX | |
| for( var i = 0; i < data["add"].length; i++ ){ | |
| if( $( "#prompt" ).val().indexOf( data["add"][i].prompt ) == -1 ){ | |
| // Adding only recommendations that are not present in the prompt | |
| var sentence = data["add"][i].prompt.replaceAll( "'", "\\'" ) ; | |
| var sentence_entity = data["add"][i].prompt.replaceAll( "'", "'" ) ; | |
| var sentence_value = data["add"][i].value.replaceAll( "'", "\\'" ) ; | |
| $( "#recommendation" ).append( '<div class="bx--tag bx--tag--green" style="cursor: pointer;" onmouseover="preview_add_recommendation(\''+ sentence + '\', \'show\')" onmouseout="preview_add_recommendation(\''+ sentence + '\', \'hide\')" onclick="add_recommendation(\''+ sentence + '\')">+ ' + sentence_value + '</div>' ) ; | |
| } | |
| } | |
| } | |
| // User status message about recommendations found | |
| if( data["add"].length == 0 && data["remove"].length == 0 ){ | |
| $( "#recommendation" ).html( "No recommendations found." ) ; | |
| } | |
| $("#prompt").data( "recommendations", data ); | |
| // renderGraph(data); | |
| }); | |
| } | |
| } | |
| }); | |
| // Generation request | |
| $( "#demo" ).on( "submit", function(e){ // Hugging Face | |
| var out = "" ; | |
| const ajax_headers = { | |
| 'Content-Type': 'application/json', | |
| 'Accept': 'application/json', | |
| 'Access-Control-Allow-Headers': '*', | |
| 'Authorization' : 'Bearer <include-token-here>', | |
| }; | |
| $.ajaxSetup({ | |
| headers: ajax_headers | |
| }); | |
| if( ajax_headers['Authorization'] == "Bearer <include-token-here>" ){ | |
| console.error( "Please inform your authorization token in the ajax header setup." ) ; | |
| } | |
| else{ | |
| $( "#generate" ).toggleClass( "bx--btn--disabled" ) ; | |
| ( function loading_animation(){ | |
| if( $( "#outcome" ).attr( "placeholder" ) == "" ){ | |
| $( "#outcome" ).attr( "placeholder", "Requesting content." ) ; | |
| } | |
| else if( $( "#outcome" ).attr( "placeholder" ).length < 21 ){ | |
| $( "#outcome" ).attr( "placeholder", $( "#outcome" ).attr( "placeholder") + "." ) ; | |
| } | |
| else{ | |
| $( "#outcome" ).attr( "placeholder", "Requesting content." ) ; | |
| } | |
| setTimeout( loading_animation, 500 ); | |
| } )() | |
| var temperature = 0.5 ; | |
| var max_new_tokens = 1000 ; | |
| var model_id = "meta-llama/Llama-3.2-11B-Vision-Instruct" | |
| $.ajax({ | |
| type: "POST", | |
| url: "https://api-inference.huggingface.co/models/" + model_id, | |
| data: JSON.stringify({ | |
| "inputs": $("#prompt").val(), | |
| "parameters": { | |
| "temperature": temperature, | |
| "max_new_tokens": max_new_tokens | |
| } | |
| }), | |
| crossDomain: true, | |
| success: function(data){ | |
| // Resetting the status of the button | |
| $( "#generate" ).toggleClass( "bx--btn--disabled" ) ; | |
| // Clearing the previous timeout | |
| if( $( "#demo" ).data( "timeoutId" ) != "" ){ | |
| clearTimeout( $( "#demo" ).data( "timeoutId" ) ); | |
| $( "#demo" ).data( "timeoutId", "" ) ; | |
| } | |
| out = data[0].generated_text.split(""); | |
| $( "#outcome" ).append( "\n\n+ ------------------------------------\n| Model: " + model_id + "\n| Temperature: " + temperature + "\n| Max new tokens: " + max_new_tokens + "\n+ ------------------------------------\n\n" ) ; | |
| // Animating the generated output | |
| ( function typing_animation(){ | |
| $( "#outcome" ).append( out.shift() ) ; | |
| $( "#outcome" ).scrollTop( $( "#outcome" )[0].scrollHeight ) ; | |
| if( out.length > 0 ) { | |
| const timeoutId = setTimeout( typing_animation, 5 ); | |
| $( "#demo" ).data( "timeoutId", timeoutId ) ; | |
| } | |
| } )() | |
| } | |
| }); | |
| } | |
| // Returning false so the form keeps user in the same page | |
| return false; | |
| }); | |
| </script> | |
| <!-- <script src="https://unpkg.com/carbon-components/scripts/carbon-components.min.js"></script> --> | |
| </body> | |
| </html> | |