質問するログイン新規登録

質問編集履歴

6

migrate_to_chroma.pyを記載し、文字数制限のためindex.htmlを削除

2026/04/09 02:40

投稿

loving
loving

スコア53

title CHANGED
File without changes
body CHANGED
@@ -332,102 +332,89 @@
332
332
  ```
333
333
 
334
334
  ```index.html
335
- <!DOCTYPE html>
336
- <html>
337
- <head>
338
- <meta charset="UTF-8">
339
- <title>外部案件検索</title>
340
- </head>
335
+ //文字数制限のため省略
341
336
 
337
+ ```
338
+ ```migrate_to_chroma.py
339
+ import sqlite3
340
+ import chromadb
342
- <body>
341
+ import requests
342
+ import os
343
+ from dotenv import load_dotenv
343
344
 
345
+ load_dotenv()
344
- <h1>ナレッジ検索</h1>
346
+ GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
345
347
 
346
- <!-- ===== 検索フォーム ===== -->
348
+ def get_embedding(text: str):
347
- <form method="POST" action="/ask" enctype="multipart/form-data">
349
+ url = f"https://generativelanguage.googleapis.com/v1beta/models/text-embedding-004:embedContent?key={GEMINI_API_KEY}"
348
-
349
- <p>質問:</p>
350
- <input type="text" name="question" style="width:400px;" required>
351
350
 
351
+ payload = {
352
- <p>質問の画像(任意):</p>
352
+ "model": "models/text-embedding-004",
353
- <input type="file" name="image">
353
+ "content": {"parts": [{"text": text}]}
354
+ }
354
355
 
355
- <br><br>
356
- <button type="submit">検索</button>
356
+ res = requests.post(url, json=payload)
357
- </form>
357
+ res.raise_for_status()
358
358
 
359
- <hr>
359
+ return res.json()["embedding"]["values"]
360
360
 
361
- <!-- ===== AI回答 ===== -->
362
- {% if answer %}
363
- <h2>AI回答</h2>
364
- <p>{{ answer }}</p>
365
- <hr>
366
- {% endif %}
367
361
 
368
- <!-- ===== 根拠表示 ===== -->
369
- {% if results %}
362
+ def migrate():
370
- <h2>根拠(事例・マニュアル)</h2>
371
363
 
364
+ conn = sqlite3.connect("db.sqlite")
372
- {% for r in results %}
365
+ cur = conn.cursor()
373
- <div style="margin-bottom:30px; border:1px solid #ccc; padding:10px;">
374
366
 
367
+ cur.execute("""
375
- <p><b>類似度:</b> {{ r.score }}</p>
368
+ SELECT id, type, question, content, answer, page, image_path
369
+ FROM knowledge
370
+ """)
376
371
 
377
- <!-- ===== 事例 ===== -->
378
- {% if r.type == "case" %}
372
+ rows = cur.fetchall()
379
- <p style="color:blue;"><b>【事例】</b></p>
373
+ conn.close()
380
374
 
381
- {% if r.question %}
382
- <p><b>質問:</b><br>{{ r.question }}</p>
375
+ chroma = chromadb.PersistentClient(path="./chroma_db")
383
- {% endif %}
384
376
 
377
+ collection = chroma.get_or_create_collection(
378
+ name="knowledge",
385
- <p><b>回答:</b><br>{{ r.answer }}</p>
379
+ metadata={"hnsw:space": "cosine"}
380
+ )
386
381
 
387
- {% if r.image %}
382
+ for row in rows:
388
- <img src="{{ url_for('static', filename='images/cases/' + r.image) }}" width="300">
383
+ id_, type_, question, content, answer, page, image = row
389
- {% else %}
390
- <p>画像なし</p>
391
- {% endif %}
392
- {% endif %}
393
384
 
394
- <!-- ===== マニュアル ===== -->
385
+ # embedding対象(ここ重要)
395
- {% if r.type == "manual" %}
396
- <p style="color:green;"><b>【マニュアル】</b></p>
386
+ text = f"{question or ''} {content or ''} {answer or ''}".strip()
397
387
 
398
- {% if r.content %}
388
+ if not text:
399
- <p><b>内容:</b><br>{{ r.content }}</p>
400
- {% endif %}
389
+ continue
401
390
 
402
- <p><b>回答:</b><br>{{ r.answer }}</p>
391
+ print("Embedding:", text[:50])
403
392
 
404
- {% if r.page %}
393
+ embedding = get_embedding(text)
405
- <p><b>ページ:</b> {{ r.page }}</p>
406
- {% endif %}
407
394
 
408
- {% if r.image %}
395
+ collection.add(
396
+ ids=[str(id_)],
409
- <img src="{{ url_for('static', filename='images/manual/' + r.image) }}" width="300">
397
+ embeddings=[embedding],
410
- {% else %}
398
+ documents=[text],
399
+ metadatas=[{
411
- <p>画像なし</p>
400
+ "type": type_ or "",
401
+ "question": question or "",
402
+ "content": content or "",
403
+ "answer": answer or "",
404
+ "page": str(page) if page else "",
412
- {% endif %}
405
+ "image": image or ""
413
- {% endif %}
406
+ }]
407
+ )
414
408
 
415
- </div>
409
+ print("✅ 移行完了")
416
410
 
417
- <hr>
418
- {% endfor %}
419
411
 
412
+ if __name__ == "__main__":
420
- {% endif %}
413
+ migrate()
421
414
 
422
- </body>
423
- </html>
424
- ```
425
- ```migrate_to_chroma.py
426
- 文字数制限で全部貼れないため省略
427
415
 
428
416
 
429
417
 
430
-
431
418
  ```
432
419
 
433
420
  ### 試したこと・調べたこと

5

migrate_to_chroma.pyについて漏れていたため修正

2026/04/09 02:33

投稿

loving
loving

スコア53

title CHANGED
File without changes
body CHANGED
@@ -422,7 +422,14 @@
422
422
  </body>
423
423
  </html>
424
424
  ```
425
+ ```migrate_to_chroma.py
426
+ 文字数制限で全部貼れないため省略
425
427
 
428
+
429
+
430
+
431
+ ```
432
+
426
433
  ### 試したこと・調べたこと
427
434
  - [ ] teratailやGoogle等で検索した
428
435
  - [x] ソースコードを自分なりに変更した

4

文法の修正

2026/04/08 12:37

投稿

loving
loving

スコア53

title CHANGED
File without changes
body CHANGED
@@ -1,6 +1,4 @@
1
- ```ここに言語を入力
2
- コード
3
- ```### 実現したいこと
1
+ ### 実現したいこと
4
2
  完全無料かつクレジットカード登録なしで、業務用チャットボットを構築したいと考えています。
5
3
 
6
4
  対象は外部案件で、業務マニュアルやQ&Aが存在します。

3

一部修正

2026/04/08 11:35

投稿

loving
loving

スコア53

title CHANGED
File without changes
body CHANGED
@@ -1,4 +1,6 @@
1
+ ```ここに言語を入力
2
+ コード
1
- ### 実現したいこと
3
+ ```### 実現したいこと
2
4
  完全無料かつクレジットカード登録なしで、業務用チャットボットを構築したいと考えています。
3
5
 
4
6
  対象は外部案件で、業務マニュアルやQ&Aが存在します。
@@ -266,9 +268,9 @@
266
268
  # ===== マニュアル =====外部案件のためマニュアルや事例の内容はダミーにしてあります
267
269
  manual_data = [
268
270
  {
269
- "content": "差額警告マークがない場合の処理",
271
+ "content": "赤線青線がない場合の処理",
270
- "keywords": "OK,差額なし,警告なし",
272
+ "keywords": "赤線,青線,
271
- "answer": "差額警告マークがなければそのままSaveする。",
273
+ "answer": "赤線青線がなければそのままSaveする。",
272
274
  "image_path": "3.png",
273
275
  "page": 3,
274
276
  "section":"(1) 処理手順"

2

一部修正

2026/04/08 11:20

投稿

loving
loving

スコア53

title CHANGED
File without changes
body CHANGED
@@ -16,7 +16,7 @@
16
16
  を知りたいです。
17
17
 
18
18
  ### 発生している問題・分からないこと
19
- この案件ではレシート画像などの画像情報が非常に重要で、
19
+ この案件では伝票画像などの画像情報が非常に重要で、
20
20
  回答は「質問文」ではなく「画像の内容」を基準に判断する必要があります。
21
21
  ただし、OCRでは読み取り精度に限界があり、正確にテキスト化できないケースも多いため画像フォルダにマニュアル画像を入れてAPIに渡しています。
22
22
 

1

マニュアルの画像の渡し方について訂正

2026/04/08 08:25

投稿

loving
loving

スコア53

title CHANGED
File without changes
body CHANGED
@@ -18,7 +18,7 @@
18
18
  ### 発生している問題・分からないこと
19
19
  この案件ではレシート画像などの画像情報が非常に重要で、
20
20
  回答は「質問文」ではなく「画像の内容」を基準に判断する必要があります。
21
- ただし、OCRでは読み取り精度に限界があり、正確にテキスト化できないケースも多いす。
21
+ ただし、OCRでは読み取り精度に限界があり、正確にテキスト化できないケースも多いため画像フォルダにマニュアル画像を入れてAPIに渡しています。
22
22
 
23
23
  さらに問題として、
24
24
  質問者の前提が誤っているケース(例:対象外と書かれていないのに対象外だと思い込んでいる)が多く、