Skip to content

Commit d41a03f

Browse files
committed
adding blog post, and adjusting blog post layouts
1 parent e12b3fb commit d41a03f

4 files changed

Lines changed: 134 additions & 0 deletions

File tree

blog/2026-04-30-llm-in-revisit.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
layout: post
3+
title: "Integrating an LLM-Based Chatbot into a reVISit Study"
4+
authors:
5+
- he
6+
- lex
7+
---
8+
9+
Studying how people interact with AI is increasingly relevant, and when that AI is embedded in an interactive system, such as a data visualization, the questions get even more interesting. With reVISit, you can now integrate an LLM-based chatbot directly into your study workflow. In this post, we walk through a working demo and show you how to adapt it for your own research.
10+
11+
<!-- truncate -->
12+
13+
Take a look at our [demo study](https://revisit.dev/study/example-llm-chatbot/). The goal of this scenario was to help people learn about a chart. In this context, the chatbot should do more than simply generate answers. It should understand the study context, respond based on relevant materials, maintain continuity across turns, and make every interaction traceable for later analysis.
14+
15+
![A screenshot of the demo study, showing a clustered heat map on the left and a chatbot on the right, where a user has asked to tell them about the chart and the bot has answered](/img/blog_posts/2026-04-30-llm/llm-chatbot-study.png)
16+
17+
Below, we describe why this chatbot is useful for studies, highlight its core features, and explain how to customize it.
18+
19+
20+
## What does this chatbot enable in our demo study?
21+
22+
In the demo study, participants can ask questions about a clustered heatmap, and the chatbot responds with streaming text. When a question requires exact data values or visual details, the chatbot can request the dataset or chart image. All inputs and outputs are tracked by [Trrack, our provenance library](https://apps.vdl.sci.utah.edu/trrackjs/), making it possible to analyze how participants interact with the chatbot and what information they request.
23+
24+
Our example uses the [OpenAI Responses API](https://developers.openai.com/api/reference/resources/responses) and is implemented with the following features:
25+
26+
- **Conversation memory:** keeps the model aware of prior turns
27+
- **Streaming responses:** reduce perceived latency and make the interface feel more responsive
28+
- **Sending the chart image and dataset only when needed:** gives the chatbot access to study materials only when required
29+
- **Recording provenance and conversation history:** makes interactions traceable for later analysis
30+
31+
## How can you use and customize it?
32+
33+
The demo is designed to be flexible (check out the [code](https://github.com/revisit-studies/study/tree/main/src/public/example-llm-chatbot/assets)). Most settings live in `ChatInterface.tsx`, where you can customize the chatbot’s behavior and study materials.
34+
35+
### Set up the API key
36+
37+
One challenge with LLM-based interfaces is keeping API keys secure in a (mostly) serverless environment such as a reVISit study. Our demo uses a proxy server to get around this problem. We created a simple proxy server for you, which you can find at [https://github.com/visdesignlab/openai-api-proxy](https://github.com/visdesignlab/openai-api-proxy).
38+
39+
After deploying the proxy, set `VITE_OPENAI_API_URL` in your `.env` file for either local development or production.
40+
41+
### Adjust the Chatbot Behavior
42+
43+
All key settings live in `ChatInterface.tsx`. The most relevant parameters are:
44+
45+
**Change the assistant behavior (system prompt)**
46+
Edit `prePrompt` and `toolPolicy` to control how the assistant responds and when it should use tools.
47+
48+
Learn more: [System instructions](https://platform.openai.com/docs/guides/responses#system-instructions)
49+
50+
**Change the model**
51+
Update `model` in both the tool-selection request and the streaming request.
52+
53+
Learn more: [Model list](https://platform.openai.com/docs/models)
54+
55+
**Change response length and style**
56+
57+
- `max_output_tokens`: maximum reply length
58+
- `temperature`: creativity level
59+
60+
Learn more: [Responses API parameters](https://platform.openai.com/docs/api-reference/responses)
61+
62+
### Replace the study materials
63+
64+
You can also swap in your own resources:
65+
66+
- Replace `assets/data/clustered-heatmap.csv` with your dataset
67+
- Replace the chart image file ID with your own uploaded chart image
68+
69+
Learn more: [Files API](https://platform.openai.com/docs/api-reference/files)
70+
71+
This makes it straightforward to adapt the demo to different tasks, datasets, and visualizations.
72+
73+
### Get the results
74+
75+
You can review participants’ interactions in the replay interface. The chat history is also included in the downloaded results in CSV or JSON format.
76+
77+
## Next steps
78+
79+
Of course, you can also build wildly different intelligent interfaces to study, using our simple example here as a launching point!
80+
81+
This setup can also be combined with [audio recording](https://revisit.dev/docs/designing-studies/think-aloud/) or [screen recording](https://revisit.dev/docs/designing-studies/record-screen/) for remote unmoderated studies.
82+
83+
If you have questions or want to share what you build, come find us in the [reVISit Slack](https://revisit-nsf.slack.com/join/shared_invite/zt-25mrh5ppi-6sDAL6HqcWJh_uvt2~~DMQ). We’d be excited to see how you apply these ideas in your own prototypes.
84+
85+
86+
## Relevant Links
87+
88+
* [Demo study](https://revisit.dev/study/example-llm-chatbot/)
89+
* [The Study Config](https://github.com/revisit-studies/study/blob/main/public/example-llm-chatbot/config.json)
90+
* [The React Component Sources](https://github.com/revisit-studies/study/tree/main/src/public/example-llm-chatbot)
91+

blog/authors.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,10 @@ team:
22
name: The ReVISit Team
33
harrison:
44
name: Lane Harrison
5+
url: https://web.cs.wpi.edu/~ltharrison/
56
lex:
67
name: Alexander Lex
8+
url: https://alexander-lex.net/
9+
he:
10+
name: Tingying He
11+
url: https://tingying-he.github.io/
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import React, { type ReactNode } from 'react';
2+
import { useBlogPost } from '@docusaurus/plugin-content-blog/client';
3+
import Link from '@docusaurus/Link';
4+
import type { Props } from '@theme/BlogPostItem/Header/Authors';
5+
6+
export default function BlogPostItemHeaderAuthors({ className }: Props): ReactNode {
7+
const {
8+
metadata: { authors },
9+
assets,
10+
} = useBlogPost();
11+
12+
if (authors.length === 0) {
13+
return null;
14+
}
15+
16+
return (
17+
<div className={className} style={{ marginTop: '-0.75rem', marginBottom: '1rem', fontSize: '0.9rem' }}>
18+
{authors.map((author, idx) => {
19+
const imageURL = assets.authorsImageUrls[idx] ?? author.imageURL;
20+
const link =
21+
author.page?.permalink ||
22+
author.url ||
23+
(author.email ? `mailto:${author.email}` : undefined);
24+
25+
return (
26+
<React.Fragment key={idx}>
27+
{idx > 0 && ', '}
28+
{link ? (
29+
<Link href={link}>{author.name}</Link>
30+
) : (
31+
<span>{author.name}</span>
32+
)}
33+
</React.Fragment>
34+
);
35+
})}
36+
</div>
37+
);
38+
}
491 KB
Loading

0 commit comments

Comments
 (0)