chansung commited on
Commit
48f38fa
·
verified ·
1 Parent(s): dc7a0c6

Upload folder using huggingface_hub

Browse files
README.md CHANGED
@@ -33,4 +33,27 @@ $ python main.py # or gradio main.py
33
  ```
34
 
35
  # Acknowledgments
36
- This is a project built during the Vertex sprints held by Google's ML Developer Programs team. We are thankful to be granted good amount of GCP credits to do this project.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  ```
34
 
35
  # Acknowledgments
36
+ This is a project built during the Vertex sprints held by Google's ML Developer Programs team. We are thankful to be granted good amount of GCP credits to do this project.# AdaptSum
37
+
38
+ AdaptSum stands for Adaptive Summarization. This project focuses on developing an LLM-powered system for dynamic summarization. Instead of generating entirely new summaries with each update, the system intelligently identifies and modifies only the necessary parts of the existing summary. This approach aims to create a more efficient and fluid summarization process within a continuous chat interaction with an LLM.
39
+
40
+ # Instructions
41
+
42
+ 1. Install dependencies
43
+ ```shell
44
+ $ pip install requirements.txt
45
+ ```
46
+
47
+ 2. Setup Gemini API Key
48
+ ```shell
49
+ $ export GEMINI_API_KEY=xxxxx
50
+ ```
51
+ > note that GEMINI API KEY should be obtained from Google AI Studio. Vertex AI is not supported at the moment (this is because Gemini SDK does not provide file uploading functionality for Vertex AI usage now).
52
+
53
+ 3. Run Gradio app
54
+ ```shell
55
+ $ python main.py # or gradio main.py
56
+ ```
57
+
58
+ # Acknowledgments
59
+ This is a project built during the Vertex sprints held by Google's ML Developer Programs team. We are thankful to be granted good amount of GCP credits to do this project.
configs/prompts.toml CHANGED
@@ -15,15 +15,6 @@ When updating the summary:
15
  * **Completeness:** Strive to be as comprehensive and detailed as possible, capturing all key points and insights.
16
  * **Conciseness:** While being detailed, also aim for conciseness and clarity in the summary.
17
  * **Update Strategy:** Instead of rewriting the entire summary each time, update only the specific portions necessary to reflect new information or changes in understanding.
18
-
19
- By following these guidelines, you will maintain an evolving summary that accurately reflects my learning and the key takeaways from our conversation."
20
-
21
- **Key improvements:**
22
-
23
- * **Clearer Instructions:** More explicit instructions on how to update the summary (i.e., updating specific portions instead of rewriting).
24
- * **Emphasis on Accuracy:** Stronger emphasis on factual accuracy and reflecting nuances.
25
- * **Conciseness:** Added a direction to balance detail with conciseness.
26
- * **Structure:** Improved organization and formatting for better readability.
27
  """
28
 
29
  system_prompt = """
@@ -31,4 +22,4 @@ Consider yourself an expert at summarizing content with a high bar
31
  for scientific rigor. However, when generating the summaries you
32
  must follow the persona of a $persona. This persona will help set
33
  the tone of the conversation.
34
- """
 
15
  * **Completeness:** Strive to be as comprehensive and detailed as possible, capturing all key points and insights.
16
  * **Conciseness:** While being detailed, also aim for conciseness and clarity in the summary.
17
  * **Update Strategy:** Instead of rewriting the entire summary each time, update only the specific portions necessary to reflect new information or changes in understanding.
 
 
 
 
 
 
 
 
 
18
  """
19
 
20
  system_prompt = """
 
22
  for scientific rigor. However, when generating the summaries you
23
  must follow the persona of a $persona. This persona will help set
24
  the tone of the conversation.
25
+ """
hf_space/.github/workflows/sync_to_spaces.yml ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Sync to Hugging Face Spaces
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ sync:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - name: Checkout GitHub Repository
15
+ uses: actions/checkout@v3
16
+
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v4
19
+ with:
20
+ python-version: "3.10"
21
+
22
+ - name: Install Hugging Face Hub CLI
23
+ run: |
24
+ python -m pip install --upgrade pip
25
+ pip install huggingface_hub
26
+
27
+ - name: Clone Hugging Face Spaces Repository
28
+ run: |
29
+ huggingface-cli login --token $HF_TOKEN --add-to-git-credential
30
+ git clone https://huggingface.co/spaces/adaptsum/demo hf_space
31
+ cd hf_space
32
+ git checkout main
33
+ env:
34
+ HF_TOKEN: ${{ secrets.HUGGINGFACE_TOKEN }}
35
+
36
+ - name: Copy Files to Hugging Face Repo
37
+ run: |
38
+ rsync -av --exclude='.git' --exclude='README.md' ./ hf_space/
39
+
40
+ - name: Merge README.md Files
41
+ run: |
42
+ cat hf_space/README.md README.md > hf_space/README_combined.md
43
+ mv hf_space/README_combined.md hf_space/README.md
44
+ rm -rf hf_space/README_combined.md
45
+
46
+ - name: Commit and Push Changes
47
+ run: |
48
+ cd hf_space
49
+ git add .
50
+ if git diff --cached --quiet; then
51
+ echo "No changes to commit"
52
+ else
53
+ huggingface-cli upload adaptsum/demo . --repo-type=space
54
+ echo "Changes have been pushed."
55
+ fi
56
+ env:
57
+ HUGGINGFACE_TOKEN: ${{ secrets.HUGGINGFACE_TOKEN }}
hf_space/configs/prompts.toml CHANGED
@@ -1,7 +1,7 @@
1
  [summarization]
2
  prompt = """
3
  Below is the initial summary of our conversation.
4
- Based on the summary and the last conversation between you(assistant) and me(user), I want to update the summary.
5
 
6
  **Initial Summary:**
7
  $previous_summary
@@ -23,5 +23,12 @@ By following these guidelines, you will maintain an evolving summary that accura
23
  * **Clearer Instructions:** More explicit instructions on how to update the summary (i.e., updating specific portions instead of rewriting).
24
  * **Emphasis on Accuracy:** Stronger emphasis on factual accuracy and reflecting nuances.
25
  * **Conciseness:** Added a direction to balance detail with conciseness.
26
- * **Structure:** Improved organization and formatting for better readability. Bullet points with Markdown would be preferred.
 
 
 
 
 
 
 
27
  """
 
1
  [summarization]
2
  prompt = """
3
  Below is the initial summary of our conversation.
4
+ Based on the summary and the last conversation between you (assistant) and me (user), I want to update the summary.
5
 
6
  **Initial Summary:**
7
  $previous_summary
 
23
  * **Clearer Instructions:** More explicit instructions on how to update the summary (i.e., updating specific portions instead of rewriting).
24
  * **Emphasis on Accuracy:** Stronger emphasis on factual accuracy and reflecting nuances.
25
  * **Conciseness:** Added a direction to balance detail with conciseness.
26
+ * **Structure:** Improved organization and formatting for better readability.
27
+ """
28
+
29
+ system_prompt = """
30
+ Consider yourself an expert at summarizing content with a high bar
31
+ for scientific rigor. However, when generating the summaries you
32
+ must follow the persona of a $persona. This persona will help set
33
+ the tone of the conversation.
34
  """
hf_space/hf_space/.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
hf_space/hf_space/.gitignore ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+
110
+ # pdm
111
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112
+ #pdm.lock
113
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114
+ # in version control.
115
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
116
+ .pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
121
+ __pypackages__/
122
+
123
+ # Celery stuff
124
+ celerybeat-schedule
125
+ celerybeat.pid
126
+
127
+ # SageMath parsed files
128
+ *.sage.py
129
+
130
+ # Environments
131
+ .env
132
+ .venv
133
+ env/
134
+ venv/
135
+ ENV/
136
+ env.bak/
137
+ venv.bak/
138
+
139
+ # Spyder project settings
140
+ .spyderproject
141
+ .spyproject
142
+
143
+ # Rope project settings
144
+ .ropeproject
145
+
146
+ # mkdocs documentation
147
+ /site
148
+
149
+ # mypy
150
+ .mypy_cache/
151
+ .dmypy.json
152
+ dmypy.json
153
+
154
+ # Pyre type checker
155
+ .pyre/
156
+
157
+ # pytype static type analyzer
158
+ .pytype/
159
+
160
+ # Cython debug symbols
161
+ cython_debug/
162
+
163
+ # PyCharm
164
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
165
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
167
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168
+ #.idea/
169
+
170
+ # PyPI configuration file
171
+ .pypirc
hf_space/hf_space/app.py ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import argparse
3
+ import asyncio
4
+ import gradio as gr
5
+ from difflib import Differ
6
+ from string import Template
7
+ from utils import load_prompt, setup_gemini_client
8
+ from configs.responses import SummaryResponses
9
+ from google.genai import types
10
+
11
+ def parse_args():
12
+ parser = argparse.ArgumentParser()
13
+ parser.add_argument("--ai-studio-api-key", type=str, default=os.getenv("GEMINI_API_KEY"))
14
+ parser.add_argument("--vertexai", action="store_true", default=False)
15
+ parser.add_argument("--vertexai-project", type=str, default="gcp-ml-172005")
16
+ parser.add_argument("--vertexai-location", type=str, default="us-central1")
17
+ parser.add_argument("--model", type=str, default="gemini-2.0-flash", choices=["gemini-1.5-flash", "gemini-2.0-flash", "gemini-2.0-flash-001"])
18
+ parser.add_argument("--seed", type=int, default=2025)
19
+ parser.add_argument("--prompt-tmpl-path", type=str, default="configs/prompts.toml")
20
+ parser.add_argument("--css-path", type=str, default="statics/styles.css")
21
+ args = parser.parse_args()
22
+ return args
23
+
24
+ def find_attached_file(filename, attached_files):
25
+ for file in attached_files:
26
+ if file['name'] == filename:
27
+ return file
28
+ return None
29
+
30
+ async def echo(message, history, state, persona):
31
+ attached_file = None
32
+ system_instruction = Template(prompt_tmpl['summarization']['system_prompt']).safe_substitute(persona=persona)
33
+
34
+ if message['files']:
35
+ path_local = message['files'][0]
36
+ filename = os.path.basename(path_local)
37
+
38
+ attached_file = find_attached_file(filename, state["attached_files"])
39
+ if attached_file is None:
40
+ path_gcp = await client.files.upload(path=path_local)
41
+ state["attached_files"].append({
42
+ "name": filename,
43
+ "path_local": path_local,
44
+ "gcp_entity": path_gcp,
45
+ "path_gcp": path_gcp.name,
46
+ "mime_type=": path_gcp.mime_type,
47
+ "expiration_time": path_gcp.expiration_time,
48
+ })
49
+ attached_file = path_gcp
50
+
51
+ user_message = [message['text']]
52
+ if attached_file: user_message.append(attached_file)
53
+
54
+ chat_history = state['messages']
55
+ chat_history = chat_history + user_message
56
+ state['messages'] = chat_history
57
+
58
+ response_chunks = ""
59
+ model_content_stream = await client.models.generate_content_stream(
60
+ model=args.model,
61
+ contents=state['messages'],
62
+ config=types.GenerateContentConfig(
63
+ system_instruction=system_instruction, seed=args.seed
64
+ ),
65
+ )
66
+ async for chunk in model_content_stream:
67
+ response_chunks += chunk.text
68
+ # when model generates too fast, Gradio does not respond that in real-time.
69
+ await asyncio.sleep(0.1)
70
+ yield (
71
+ response_chunks,
72
+ state,
73
+ state['summary_diff_history'][-1] if len(state['summary_diff_history']) > 1 else "",
74
+ state['summary_history'][-1] if len(state['summary_history']) > 1 else "",
75
+ gr.Slider(
76
+ visible=False if len(state['summary_history']) <= 1 else True,
77
+ interactive=False if len(state['summary_history']) <= 1 else True,
78
+ ),
79
+ )
80
+
81
+ # make summary
82
+ response = await client.models.generate_content(
83
+ model=args.model,
84
+ contents=[
85
+ Template(
86
+ prompt_tmpl['summarization']['prompt']
87
+ ).safe_substitute(
88
+ previous_summary=state['summary'],
89
+ latest_conversation=str({"user": message['text'], "assistant": response_chunks})
90
+ )
91
+ ],
92
+ config=types.GenerateContentConfig(
93
+ system_instruction=system_instruction,
94
+ seed=args.seed,
95
+ response_mime_type='application/json',
96
+ response_schema=SummaryResponses
97
+ )
98
+ )
99
+
100
+ prev_summary = state['summary_history'][-1] if len(state['summary_history']) >= 1 else ""
101
+
102
+ state['summary'] = (
103
+ response.parsed.summary
104
+ if getattr(response.parsed, "summary", None) is not None
105
+ else response.text
106
+ )
107
+ state['summary_history'].append(
108
+ response.parsed.summary
109
+ if getattr(response.parsed, "summary", None) is not None
110
+ else response.text
111
+ )
112
+ state['summary_diff_history'].append(
113
+ [
114
+ (token[2:], token[0] if token[0] != " " else None)
115
+ for token in Differ().compare(prev_summary, state['summary'])
116
+ ]
117
+ )
118
+
119
+ yield (
120
+ response_chunks,
121
+ state,
122
+ state['summary_diff_history'][-1],
123
+ state['summary_history'][-1],
124
+ gr.Slider(
125
+ maximum=len(state['summary_history']),
126
+ value=len(state['summary_history']),
127
+ visible=False if len(state['summary_history']) == 1 else True, interactive=True
128
+ ),
129
+ )
130
+
131
+ def change_view_toggle(view_toggle):
132
+ if view_toggle == "Diff":
133
+ return (
134
+ gr.HighlightedText(visible=True),
135
+ gr.Markdown(visible=False)
136
+ )
137
+ else:
138
+ return (
139
+ gr.HighlightedText(visible=False),
140
+ gr.Markdown(visible=True)
141
+ )
142
+
143
+ def navigate_to_summary(summary_num, state):
144
+ return (
145
+ state['summary_diff_history'][summary_num-1],
146
+ state['summary_history'][summary_num-1]
147
+ )
148
+
149
+ def main(args):
150
+ style_css = open(args.css_path, "r").read()
151
+
152
+ global client, prompt_tmpl, system_instruction
153
+ client = setup_gemini_client(args)
154
+ prompt_tmpl = load_prompt(args)
155
+
156
+ ## Gradio Blocks
157
+ with gr.Blocks(css=style_css) as demo:
158
+ # State per session
159
+ state = gr.State({
160
+ "messages": [],
161
+ "attached_files": [],
162
+ "summary": "",
163
+ "summary_history": [],
164
+ "summary_diff_history": []
165
+ })
166
+
167
+ with gr.Column():
168
+ gr.Markdown("# Adaptive Summarization")
169
+ gr.Markdown("AdaptSum stands for Adaptive Summarization. This project focuses on developing an LLM-powered system for dynamic summarization. Instead of generating entirely new summaries with each update, the system intelligently identifies and modifies only the necessary parts of the existing summary. This approach aims to create a more efficient and fluid summarization process within a continuous chat interaction with an LLM.")
170
+
171
+ with gr.Column():
172
+ with gr.Accordion("Adaptively Summarized Conversation", elem_id="adaptive-summary-accordion", open=False):
173
+ with gr.Row(elem_id="view-toggle-btn-container"):
174
+ view_toggle_btn = gr.Radio(
175
+ choices=["Diff", "Markdown"],
176
+ value="Markdown",
177
+ interactive=True,
178
+ elem_id="view-toggle-btn"
179
+ )
180
+
181
+ summary_diff = gr.HighlightedText(
182
+ label="Summary so far",
183
+ # value="No summary yet. As you chat with the assistant, the summary will be updated automatically.",
184
+ combine_adjacent=True,
185
+ show_legend=True,
186
+ color_map={"-": "red", "+": "green"},
187
+ elem_classes=["summary-window"],
188
+ visible=False
189
+ )
190
+
191
+ summary_md = gr.Markdown(
192
+ label="Summary so far",
193
+ value="No summary yet. As you chat with the assistant, the summary will be updated automatically.",
194
+ elem_classes=["summary-window"],
195
+ visible=True
196
+ )
197
+
198
+ summary_num = gr.Slider(label="summary history", minimum=1, maximum=1, step=1, show_reset_button=False, visible=False)
199
+
200
+ view_toggle_btn.change(change_view_toggle, inputs=[view_toggle_btn], outputs=[summary_diff, summary_md])
201
+ summary_num.release(navigate_to_summary, inputs=[summary_num, state], outputs=[summary_diff, summary_md])
202
+
203
+ with gr.Column("persona-dropdown-container", elem_id="persona-dropdown-container"):
204
+ persona = gr.Dropdown(
205
+ ["expert", "novice", "regular practitioner", "high schooler"],
206
+ label="Summary Persona",
207
+ info="Control the tonality of the conversation.",
208
+ min_width="auto",
209
+ )
210
+
211
+ with gr.Column("chat-window", elem_id="chat-window"):
212
+ gr.ChatInterface(
213
+ multimodal=True,
214
+ type="messages",
215
+ fn=echo,
216
+ additional_inputs=[state, persona],
217
+ additional_outputs=[state, summary_diff, summary_md, summary_num],
218
+ )
219
+
220
+ return demo
221
+
222
+ if __name__ == "__main__":
223
+ args = parse_args()
224
+ demo = main(args)
225
+ demo.launch()
hf_space/hf_space/configs/prompts.toml ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [summarization]
2
+ prompt = """
3
+ Below is the initial summary of our conversation.
4
+ Based on the summary and the last conversation between you(assistant) and me(user), I want to update the summary.
5
+
6
+ **Initial Summary:**
7
+ $previous_summary
8
+
9
+ **Last Conversation:**
10
+ $latest_conversation
11
+
12
+ When updating the summary:
13
+ * **Focus:** Only include information we have explicitly discussed in this session. Do not introduce any new information or topics, even if you have prior knowledge.
14
+ * **Accuracy:** Ensure the summary is factually accurate and reflects the nuances of our discussion.
15
+ * **Completeness:** Strive to be as comprehensive and detailed as possible, capturing all key points and insights.
16
+ * **Conciseness:** While being detailed, also aim for conciseness and clarity in the summary.
17
+ * **Update Strategy:** Instead of rewriting the entire summary each time, update only the specific portions necessary to reflect new information or changes in understanding.
18
+
19
+ By following these guidelines, you will maintain an evolving summary that accurately reflects my learning and the key takeaways from our conversation."
20
+
21
+ **Key improvements:**
22
+
23
+ * **Clearer Instructions:** More explicit instructions on how to update the summary (i.e., updating specific portions instead of rewriting).
24
+ * **Emphasis on Accuracy:** Stronger emphasis on factual accuracy and reflecting nuances.
25
+ * **Conciseness:** Added a direction to balance detail with conciseness.
26
+ * **Structure:** Improved organization and formatting for better readability. Bullet points with Markdown would be preferred.
27
+ """
hf_space/hf_space/configs/responses.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+
3
+ class SummaryResponses(BaseModel):
4
+ summary: str
hf_space/hf_space/requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ google-genai==0.7.0
2
+ toml
3
+ gradio
hf_space/hf_space/statics/styles.css ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .summary-window {
2
+ height: 550px !important;
3
+ /* border: dashed 1px #e0e0e0 !important; */
4
+ border-radius: 10px !important;
5
+ padding: 4px;
6
+ }
7
+
8
+ .summary-window > label {
9
+ display: none !important;
10
+ }
11
+
12
+ #view-toggle-btn-container > div {
13
+ border: none !important;
14
+ }
15
+
16
+ #view-toggle-btn > span {
17
+ display: none !important;
18
+ }
19
+
20
+ #view-toggle-btn > div:nth-child(3) {
21
+ margin: auto !important;
22
+ width: fit-content !important;
23
+ }
24
+
25
+ #adaptive-summary-accordion {
26
+ position: absolute !important;
27
+ z-index: 100 !important;
28
+ box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
29
+ }
30
+
31
+ #chat-window {
32
+ margin-top: 40px !important;
33
+ }
34
+
35
+ #chat-window > div > div:nth-child(1) {
36
+ height: 600px !important;
37
+ }
38
+
39
+ .textfield {
40
+ line-height: 1.7 !important;
41
+ }
42
+
43
+ .textspan {
44
+ padding: 0px !important;
45
+ margin: 0px !important;
46
+ line-height: 1.7 !important;
47
+ }
48
+
49
+ @media (prefers-color-scheme: dark) {
50
+ #adaptive-summary-accordion {
51
+ /* White-ish shadow for dark themes */
52
+ box-shadow: 5px 5px 10px rgba(245, 245, 245, 0.2); /* Or any other white-ish color you prefer */
53
+ }
54
+ }
hf_space/hf_space/utils.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import toml
2
+ from google import genai
3
+
4
+ def load_prompt(args):
5
+ with open(args.prompt_tmpl_path, 'r') as f:
6
+ prompts = toml.load(f)
7
+
8
+ return prompts
9
+
10
+ def setup_gemini_client(args):
11
+ if args.vertexai:
12
+ client = genai.Client(
13
+ vertexai=args.vertexai,
14
+ project=args.vertexai_project,
15
+ location=args.vertexai_location
16
+ )
17
+ else:
18
+ client = genai.Client(
19
+ api_key=args.ai_studio_api_key,
20
+ )
21
+
22
+ return client
hf_space/requirements.txt CHANGED
@@ -1,3 +1,3 @@
1
  google-genai==0.7.0
2
  toml
3
- gradio
 
1
  google-genai==0.7.0
2
  toml
3
+ gradio
hf_space/statics/styles.css CHANGED
@@ -1,5 +1,5 @@
1
  .summary-window {
2
- height: 550px !important;
3
  /* border: dashed 1px #e0e0e0 !important; */
4
  border-radius: 10px !important;
5
  padding: 4px;
@@ -28,9 +28,9 @@
28
  box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
29
  }
30
 
31
- #chat-window {
32
  margin-top: 40px !important;
33
- }
34
 
35
  #chat-window > div > div:nth-child(1) {
36
  height: 600px !important;
@@ -46,9 +46,6 @@
46
  line-height: 1.7 !important;
47
  }
48
 
49
- @media (prefers-color-scheme: dark) {
50
- #adaptive-summary-accordion {
51
- /* White-ish shadow for dark themes */
52
- box-shadow: 5px 5px 10px rgba(245, 245, 245, 0.2); /* Or any other white-ish color you prefer */
53
- }
54
  }
 
1
  .summary-window {
2
+ height: 600px !important;
3
  /* border: dashed 1px #e0e0e0 !important; */
4
  border-radius: 10px !important;
5
  padding: 4px;
 
28
  box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
29
  }
30
 
31
+ /* #chat-window {
32
  margin-top: 40px !important;
33
+ } */
34
 
35
  #chat-window > div > div:nth-child(1) {
36
  height: 600px !important;
 
46
  line-height: 1.7 !important;
47
  }
48
 
49
+ #persona-dropdown-container {
50
+ margin-top: 40px !important;
 
 
 
51
  }
hf_space/utils.py CHANGED
@@ -9,14 +9,18 @@ def load_prompt(args):
9
 
10
  def setup_gemini_client(args):
11
  if args.vertexai:
12
- client = genai.Client(
13
- vertexai=args.vertexai,
14
- project=args.vertexai_project,
15
- location=args.vertexai_location
 
 
16
  )
17
  else:
18
- client = genai.Client(
19
- api_key=args.ai_studio_api_key,
 
 
20
  )
21
 
22
  return client
 
9
 
10
  def setup_gemini_client(args):
11
  if args.vertexai:
12
+ client = genai.client.AsyncClient(
13
+ genai.client.ApiClient(
14
+ vertexai=args.vertexai,
15
+ project=args.vertexai_project,
16
+ location=args.vertexai_location
17
+ )
18
  )
19
  else:
20
+ client = genai.client.AsyncClient(
21
+ genai.client.ApiClient(
22
+ api_key=args.ai_studio_api_key
23
+ )
24
  )
25
 
26
  return client